高分相求:ShowModal方法的另类实现,请对VCL机制了解的朋友看看. [1000分] (100分)

  • 主题发起人 轻舞肥羊
  • 开始时间

轻舞肥羊

Unregistered / Unconfirmed
GUEST, unregistred user!
3.不影响正常使用,尽量不用其它地方配合,只在一个基类中完成
这点最重要

例子好象有问题,程序第二次才能退出
另外,不能用Action不能忍受!!!

早知道就好了,就不用费这么大劲了 -_-

0731ys@sohu.com

我现在想在不修改VCL源码的基础上实现,看来要自己写一个任务栏按钮了:(
 
L

LiChaoHui

Unregistered / Unconfirmed
GUEST, unregistred user!
上面,我已经给你写了一个UBase.pas单元,
实现了一个基类,你所有的窗口从它继承就可以了
第三点也完全符合呀!

我实现了一个基类,但是同时也对VCL源码做了大量的修改(我没有办法不这么做),
你找到那些修改的地方就明白了,继承是不能那解决问题的,

例子的目的就是要实现程序的“复活”,改变主窗口,
那种方法,我已经放弃了,
我会把我目前写的一个东西发给你,
我修改了Forms,Dialogs,单元,并实现了ExForms单元,
写了几个基类,主要用于bpl中对象和主框架通信用的,
但是,这个模型不符合你的第一和第二点要求
 
Y

ysai

Unregistered / Unconfirmed
GUEST, unregistred user!
TO LiChaoHui:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1931625
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1931626
另,任务栏菜单平铺怎么解决?还有一系列的问题....越深入越难了...
 
L

LiChaoHui

Unregistered / Unconfirmed
GUEST, unregistred user!
发送了几次都不能成功,于是,我把程序上传到playicq上面了
http://new.playicq.com/dispdocnew.php?id=5184

你先看看吧,我始终觉得在这个问题上面浪费了太多的时间,
但我的顽固和执着却一直在继续,通过对Forms单元的深入研究,
这也算是取得的一点点成果吧,如果Borland的专家知道我在这上面
耗费了巨大的心思,它也许不会把TApplication对象设计成现在的这种样子了,

事实上,在CLX中这种窗口机制已经改变,但是CLX实在是不适合在Windows平台下的开发
样子太难看了,还从来没有使用它的想法
 

轻舞肥羊

Unregistered / Unconfirmed
GUEST, unregistred user!
TO LiChaoHui:
老大你的代码实在难懂,Forms单元的代码没找到注释,而且只能用于D6,太不方便了.
最惨的是,我用的是D7~~用你的东东版本怎么办是个大问题.看不懂的代码我还不想用.

to xeen:
大侠什么时候点解点解?

还是想在不修改VCL源码的基础上实现,看来有时间还是自己写个东东代替Application
在任务栏上的按钮,如果时间允许的话...

欢迎继续讨论~~~~
 
W

wfzha

Unregistered / Unconfirmed
GUEST, unregistred user!
to 楼主
LiChaoHui的办法可行,第一种我没试(太懒)
第二种如下,我用的也是d7
后面的没看清楚,当施费话
public
procedure DoShow
override;
procedure WMSysCommand(var Message: TWMSysCommand)
message WM_SYSCOMMAND;

{ Public declarations }
end;

var
Form2: TForm2;

implementation

{$R *.dfm}


{ TForm2 }

procedure TForm2.DoShow;
begin
if (fsModal in FormState) then
begin
EnableWindow(Application.Handle, True);
end;
inherited;
end;

procedure TForm2.WMSysCommand(var Message: TWMSysCommand);
begin
if (fsModal in FormState) and
(Message.CmdType and $FFF0 = SC_MINIMIZE) then
begin
Application.Minimize;
end
else inherited;
end;
 
L

LiChaoHui

Unregistered / Unconfirmed
GUEST, unregistred user!
to 肥羊:
如果仅仅是修改任务栏的按钮的话,那是非常简单的,
但是修改后会带来一系列的问题,这就是我同时修改Forms, Dialogs单元的原因
原来,我是也不大算修改Forms,更没有想到要修改Dialogs
但我也是无奈的选择,因为VCL中实现Windows本身的窗口模式,实在是太不合适了,
会出现一些你不想看到的现象,
所以,我觉得,最好还是不修改的好

我可以告诉你,我所作的几方面的修改,
第一 使用SetWindowLong 在Application 的窗口风格中加入 WS_EX_TOOLWINDOW
使其在任务栏上消失,
第二,覆盖主窗口的CreateParams方法,修改窗口创建参数,设置其父窗口为桌面,
使主窗口在任务栏上出现按钮,
第三,当一个窗口或对话框的拥有者Owner为一个窗口时,如果不是子窗口,则自动成为
其弹出窗口,也是通过CreateParams方法实现的
第四,覆盖主窗口的消息WM_SYSCOMMAND使其能够正常的最小化和回复窗口,
第五,修改所有消息框以及各种对话框的部分代码,使其以弹出窗口的什么显示,
否则,在切换任务时,会得到一种尴尬的现象,这时需要修改Forms,Dialogs
第六,修改Forms单元,使MDI父窗口的客户区,不出现滚动条

按照上面的修改方法,在D7下面进行修改也不是很难的,但是要修改的地方也是很多的
你自己也能够很容易的完成的
 
L

LiChaoHui

Unregistered / Unconfirmed
GUEST, unregistred user!
自己写一个TApplication类也不是容易的事情,因为Application是个全局对象,
很多类都和它有依赖关系,而且Dialogs单元中也有很多不符合我的所谓
窗口模式的代码,不修改是解决不了问题的,问题没有你想的那么简单,
我在很早之前就已经像你现在那么想了,克现在,我不还是修改了其它的很多东西

你说,看不懂的代码,你不想用,你可以把2我所改的你看不懂的地方贴出来,
我解释给你听,而Borland自己的代码,我可是不可能全部解释给你听的,
你如果因此而不用它,我也没有办法了
 
W

wbtvc

Unregistered / Unconfirmed
GUEST, unregistred user!
这样的问题也给1000分,晕~
 
C

ChinaYA

Unregistered / Unconfirmed
GUEST, unregistred user!
呵呵!讨论的还真热烈。
其实VCL的代码做的相不错了,不过需要你在此机制上进行扩充,如果你想使用API直接控制窗口的话,那么就会出现一些意想不到的问题: 嘻嘻 ! 这大概就是微软和宝蓝的根本区别——只要是基于Windows平台的。
 
L

LiChaoHui

Unregistered / Unconfirmed
GUEST, unregistred user!
是啊,这就是,简单封装和高层次封装的区别,
to wbtvc
值不值,只有楼主自己清楚,楼主觉的值,就值,
如果楼主觉的不值,也没办法了,。。。。
 

轻舞肥羊

Unregistered / Unconfirmed
GUEST, unregistred user!
好东西大家分享,研究出来对其他需要的大富翁也有帮助嘛,分数并不代表什么,刺激一下消费罢了,呵呵...

Dialogs还没试过,看VCL源码,显示Dialogs用了Application的句柄,可能不能避免修改源码
 
L

LiChaoHui

Unregistered / Unconfirmed
GUEST, unregistred user!
必须使对话框成为弹出式窗口,否则切换任务时会有不好的现象出现
而且fsStayOnTop的窗口也可以直接用弹出式窗口实现了
 
W

wbtvc

Unregistered / Unconfirmed
GUEST, unregistred user!
sorry,没看清题目,呵呵
 

轻舞肥羊

Unregistered / Unconfirmed
GUEST, unregistred user!
TO LiChaoHui:
问题继续,我用下面的过程想实现Application的菜单与当前活动窗体的菜单一致.

procedure TFrmBase.UpdateApplicationMenu;
var
i : Integer;
iCount : Integer;
hMenu : HWND;
psMenu : array[0..MAXBYTE] of char;
uFlags : Integer;
begin
hMenu := GetSystemMenu(Application.Handle,False);
iCount := GetMenuItemCount(hMenu);
for i := 0 to iCount - 1 do
DeleteMenu(hMenu,0,MF_BYPOSITION);

hMenu := GetSystemMenu(Handle,False);
iCount := GetMenuItemCount(hMenu);
for i := 0 to iCount - 1 do
begin
GetMenuString(hMenu,i,psMenu,MAXBYTE,MF_BYPOSITION);
if StrPas(psMenu) = '' then
uFlags := MF_SEPARATOR
else
uFlags := MF_BYCOMMAND;
AppendMenu(
GetSystemMenu(Application.Handle,False),
uFlags,
GetMenuItemID(hMenu,i),
psMenu);
end;
end;

另,syAppHandler单元的主过程改为成如下
function NewWndProc(
Handle : HWND;
Msg : Integer;
wParam : Longint;
lParam : Longint
):Longint
stdcall;
begin
Result := 0;
if Msg = WM_SYSCOMMAND then
begin
case wParam of
SC_MINIMIZE : //最小化消息
begin
if Assigned(Screen.ActiveForm) then
SetWindowPos(
Application.Handle,
Screen.ActiveForm.Handle,
Screen.ActiveForm.Left,
Screen.ActiveForm.Top,
Screen.ActiveForm.Width,
0,SWP_SHOWWINDOW);
DefWindowProc(Application.Handle,WM_SYSCOMMAND,SC_MINIMIZE,0);
end;
SC_RESTORE : //还原消息
begin
if Assigned(Screen.ActiveForm) then
SetWindowPos(
Application.Handle,
Screen.ActiveForm.Handle,
Screen.ActiveForm.Left,
Screen.ActiveForm.Top,
Screen.ActiveForm.Width,
0,SWP_SHOWWINDOW);
DefWindowProc(Application.Handle,WM_SYSCOMMAND,SC_RESTORE,0);
end;
SC_CLOSE : //关闭消息
if (Application.MainForm = nil) and Assigned(Screen.ActiveForm) then
Screen.ActiveForm.Close
else
Result := CallWindowProc(OldWProc, Handle, Msg, wParam, lParam);
else //其它默认消息
if Assigned(Screen.ActiveForm) then
if Screen.ActiveForm.FormStyle <> fsMDIChild then
Result := DefWindowProc(
Screen.ActiveForm.Handle,WM_SYSCOMMAND,wParam,lParam)
else
Result := DefWindowProc(
Application.MainForm.Handle,WM_SYSCOMMAND,wParam,lParam)
else
Result := CallWindowProc(OldWProc, Handle, Msg, wParam, lParam);
end
//case
end
else
Result := CallWindowProc(OldWProc, Handle, Msg, wParam, lParam);
end;

我在工程中MDI主窗体建立之前SHOW了一个登录窗体,所有动作都正常,也自动更新
但建立了主窗体(MDI)后,菜单的Enabled不更新了.

现在我想知道,更新系统菜单的Enabled是什么消息?TApplication是怎么处理的?
我得自己处理了,像最大化,最小化等...

另,我加上的菜单项前面没有系统默认的图标,像关闭前有个×的图标,应该怎么加来着?
 
J

JamesBond_L

Unregistered / Unconfirmed
GUEST, unregistred user!
早沒有發現,浪費~
 

魔鬼大师

Unregistered / Unconfirmed
GUEST, unregistred user!
S

stargazer

Unregistered / Unconfirmed
GUEST, unregistred user!
建议大家参考一下KOL的代码。相信会有所帮助。
 
W

wlmmlw

Unregistered / Unconfirmed
GUEST, unregistred user!
为什么一定要修改showmodal 呢???
 
B

barton

Unregistered / Unconfirmed
GUEST, unregistred user!
楼主要求的其实就是类似于VC++下显示对话框的形式。Form与Dialog处理消息的方式确实
差异很大,这就是Delphi不如VC++的原因。Delphi在处理对话框方面所花的代价比VC++大
得多。究其原因,很简单:一个对话框只需要顶层窗口过程调用对话框窗口过程就行了,
而Form与Dialog资源有着太大的差异。要做到完全一致,几乎是不可能的。相比之下,
KOL是做得比较完善的了。不过一般人不会用的。KOL(MCK)整个项目中只能有一个窗体能够
ShowModal,而这个窗体就是主窗体(顶层窗口),相当于Application,进而实现主消息循
环。
我认为既然你已经用了Delphi,就得接受Delphi现如今的这种安排,你改来改去谁知会冒
出什么新的问题来?
我自己也写了个类库(与KOL完全不同的),花了我巨多精力,但至今还不敢投入商业应用。
 
顶部