Borland Delphi 窗口类核心问题,请大家进入讨论!!! (200分)

  • 主题发起人 主题发起人 pcexplorer
  • 开始时间 开始时间
就是为了把系统菜单设成与标准的一样吗?<br>这么简单的事情要不要搞这么多动作啊? FAINT!<br>先看看为什么Delphi程序的系统菜单会少两项吧
 
同意xianjun!<br>要实现任务栏的菜单和主窗口的系统菜单一样?<br>如果是以任务栏的菜单为标准,改主窗口的系统菜单,可以通过getsystemmenu()等函数实现!<br>如果是以主窗口的系统菜单为标准,改任务栏的菜单,则通过FindWindow()等找到句柄,可以截获修改或者自绘!
 
去他吗的--低手莫入!!!
 
哈哈,有意思 不明白什么高手低手
 
应改为高叫低叫才合适
 
to bbkxjy:<br>照做了,但是效果不理想,最小化,最大化都会先到屏幕的左上角去。
 
任务条上的menu是Application的,窗口上的是form自己的.<br>你在Form的OnCreate事件中分别用<br>HM := GetSystemMenu(Form1.handle,false);<br>AppendMenu(HM,MF_STRING,2000,'mymenuitem');<br>和<br>HM := GetSystemMenu(Application.handle,false);<br>AppendMenu(HM,MF_STRING,2000,'mymenuitem');<br>就知道了,如果还不死心,再看看<br>procedure TApplication.CreateHandle;<br>begin<br>...<br>&nbsp; &nbsp; SysMenu := GetSystemMenu(FHandle, False);<br>&nbsp; &nbsp; DeleteMenu(SysMenu, SC_MAXIMIZE, MF_BYCOMMAND);<br>&nbsp; &nbsp; DeleteMenu(SysMenu, SC_SIZE, MF_BYCOMMAND);<br>&nbsp; &nbsp; if NewStyleControls then DeleteMenu(SysMenu, SC_MOVE, MF_BYCOMMAND);<br>&nbsp; &nbsp;// 正好少了三项<br>end;<br><br>如果再看看<br>procedure TCustomForm.WMNCCreate(var Message: TWMNCCreate);<br>就知道为什么Delphi中Dialog和VC,VB中的不同了.<br><br>那么为什么用VC,VB中任务条上的系统菜单和Form上是一样的,很简单<br>BOOL CSsApp::InitInstance()<br>{<br> AfxEnableControlContainer();<br><br> // Standard initialization<br> // If you are not using these features and wish to reduce the size<br> // &nbsp;of your final executable, you should remove from the following<br> // &nbsp;the specific initialization routines you do not need.<br><br>#ifdef _AFXDLL<br> Enable3dControls(); // Call this when using MFC in a shared DLL<br>#else<br> Enable3dControlsStatic(); // Call this when linking to MFC statically<br>#endif<br><br> CSsDlg dlg;<br>[blue] m_pMainWnd = &amp;dlg;[/blue] <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int nResponse = dlg.DoModal();<br> if (nResponse == IDOK)<br> {<br> // TODO: Place code here to handle when the dialog is<br> // &nbsp;dismissed with OK<br> }<br> else if (nResponse == IDCANCEL)<br> {<br> // TODO: Place code here to handle when the dialog is<br> // &nbsp;dismissed with Cancel<br> }<br><br> // Since the dialog has been closed, return FALSE so that we exit the<br> // &nbsp;application, rather than start the application's message pump.<br> return FALSE;<br>}<br><br>蓝色的那一行就是答案.<br><br>
 
TO bluerain:<br>&nbsp; 原理我当然知道,AppendMenu和DeleteMenu以及相应command id有谁不知道?<br>&nbsp; 现在的问题是怎么解决,怎么解决delphi中的TApplication菜单和MainForm菜单<br>的同步(或者说模拟)!!<br>&nbsp;
 
{这是一个封装标准Windows窗口的类,其中TAppFrm窗口类}<br>{是具有标准Windows风格主窗口类,TAppFrm窗口类必须和}<br>{TAppChildFrm窗口类一起使用}<br>unit AppWnd;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;<br><br>type<br>&nbsp; TAppFrm = class(TForm)<br>&nbsp; &nbsp; procedure CreateParams(var Params:TCreateParams);override;<br>&nbsp; private<br>&nbsp; &nbsp; FParentFrm:TForm;<br>&nbsp; &nbsp; procedure WMSysCommand(var Msg:TWMSysCommand);message WM_SYSCOMMAND;<br>&nbsp; &nbsp; procedure WMMenuSelect(var Msg:TWMMenuSelect);message WM_MENUSELECT;<br>&nbsp; &nbsp; procedure CreateAppWnd;<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; //property ParentFrm:TForm read FParentFrm write FParentFrm;<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; &nbsp; constructor Create(AOwner: TComponent); override;<br>&nbsp; &nbsp; destructor Destroy; override;<br>&nbsp; end;<br><br>{--------------------------------------------------------------}<br>&nbsp; TAppChildFrm = class(TForm)<br>&nbsp; &nbsp; procedure CreateParams(var Params:TCreateParams);override;<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; &nbsp; constructor Create(AOwner: TComponent); override;<br>&nbsp; &nbsp; destructor Destroy; override;<br>&nbsp; end;<br>&nbsp; <br>{--------------------------------------------------------------}<br>implementation<br><br>{ TAppFrm }<br><br>constructor TAppFrm.Create(AOwner: TComponent);<br>begin<br>&nbsp; if AOwner is TForm then<br>&nbsp; &nbsp; FParentFrm:=AOwner as TForm<br>&nbsp; else<br>&nbsp; &nbsp; FParentFrm:=nil;<br>&nbsp; inherited Create(AOwner);<br>&nbsp; CreateAppWnd;<br>end;<br><br>procedure TAppFrm.CreateAppWnd;<br>begin<br>&nbsp; SetWindowLong(Application.Handle,GWL_EXSTYLE,<br>&nbsp; &nbsp; &nbsp; &nbsp; GetWindowLong(Application.Handle,GWL_EXSTYLE) or WS_EX_TOOLWINDOW);<br>end;<br><br>procedure TAppFrm.CreateParams(var Params: TCreateParams);<br>begin<br>&nbsp; inherited CreateParams(Params);<br>&nbsp; if not Assigned(Application.MainForm) then<br>&nbsp; &nbsp; Params.ExStyle:=WS_EX_APPWINDOW;<br>&nbsp; if Assigned(FParentFrm) then<br>&nbsp; &nbsp; Params.WndParent:=FParentFrm.Handle;<br>end;<br><br>destructor TAppFrm.Destroy;<br>begin<br>&nbsp; inherited;<br>&nbsp; //<br>end;<br><br>procedure TAppFrm.WMMenuSelect(var Msg: TWMMenuSelect);<br>begin<br>&nbsp; inherited;<br>&nbsp; with Application do<br>&nbsp; &nbsp; case Msg.IDItem of<br>&nbsp; &nbsp; &nbsp; SC_MINIMIZE :Hint:='将该窗口缩小为图标。';<br>&nbsp; &nbsp; &nbsp; SC_CLOSE &nbsp; &nbsp;:Hint:='关闭该窗口。';<br>&nbsp; &nbsp; &nbsp; SC_MAXIMIZE :Hint:='将该窗口扩大为全屏幕显示。';<br>&nbsp; &nbsp; &nbsp; SC_SIZE &nbsp; &nbsp; :Hint:='重新调整该窗口的尺寸。';<br>&nbsp; &nbsp; &nbsp; SC_MOVE &nbsp; &nbsp; :Hint:='移动该窗口。';<br>&nbsp; &nbsp; &nbsp; SC_RESTORE &nbsp;:Hint:='将该窗口恢复为正常大小。'<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; if Msg.MenuFlag = MF_SYSMENU then<br>&nbsp; &nbsp; &nbsp; &nbsp; Hint:='';<br>&nbsp; &nbsp; end;<br>end;<br><br>procedure TAppFrm.WMSysCommand(var Msg: TWMSysCommand);<br>begin<br>&nbsp; if Msg.CmdType=SC_MINIMIZE then<br>&nbsp; &nbsp; WindowState:=wsMinimized<br>&nbsp; else<br>&nbsp; &nbsp; inherited;<br>end;<br><br>{--------------------------------------------------------------}<br><br>{ TAppChildFrm }<br><br>constructor TAppChildFrm.Create(AOwner: TComponent);<br>begin<br>&nbsp; inherited;<br>&nbsp; //<br>end;<br><br>procedure TAppChildFrm.CreateParams(var Params:TCreateParams);<br>begin<br>&nbsp; inherited CreateParams(Params);<br>&nbsp; Params.WndParent:=Application.MainForm.Handle;<br>end;<br><br>destructor TAppChildFrm.Destroy;<br>begin<br>&nbsp; inherited;<br>&nbsp; //<br>end;<br><br>{--------------------------------------------------------------}<br><br>end.<br>
 
既然大家都是高高高手,原理都知道,menu操作也是有谁不知道的,如何模拟<br>就更是小菜一碟了,呵呵[:D].<br>但是我奇怪,为什么原理都知道了,menu操作也是人人都会,为什么还无法模拟.<br>奇怪.[8D]
 
TO BLUERAIN:<br>你也想得太简单了吧?<br>要显示出来当然不是难事了,难在消息的处理,以及要避开TApplication已有的处理。<br>TApplication的所有代码都假设了只有“还原”,“最小化”,“关闭”这三个消息。<br><br>没有人称自己是高手,您有能耐的话,跟pcexplorer和bbkxjy一样把具体方案或者代<br>码贴出来好了!<br><br>我这里贴一个组件,除了最大化略有bug之外,其他的都能正常运行,希望大家探讨。<br><br>unit cmpStandardSystemMenu;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus;<br><br>const<br>&nbsp; scxRESTORE &nbsp;= $fff0;<br>&nbsp; scxMINIMIZE = $fff2;<br>&nbsp; scxMAXIMIZE = $fff3;<br>&nbsp; scxSIZE &nbsp; &nbsp; = $fff4;<br>&nbsp; scxMOVE &nbsp; &nbsp; = $fff5;<br><br>type<br>&nbsp; TStandardSystemMenu = class(TComponent)<br>&nbsp; private<br>&nbsp; &nbsp; fMenuHandle : HMenu;<br>&nbsp; &nbsp; fWindowMenuHandle : HMenu;<br>&nbsp; &nbsp; fObjectInstance : pointer;<br>&nbsp; &nbsp; fOldOwnerWindowProc : TFNWndProc;<br><br>&nbsp; &nbsp; fSysObjectInstance : pointer;<br>&nbsp; &nbsp; fOldSysWindowProc : TFNWndProc;<br><br>&nbsp; &nbsp; fIconic : boolean;<br>&nbsp; &nbsp; fMaximized : boolean;<br><br>&nbsp; &nbsp; procedure CloneSystemMenu;<br>&nbsp; &nbsp; procedure OwnerWindowProc(var msg: TMessage);<br>&nbsp; &nbsp; procedure SysOwnerWindowProc(var msg: TMessage);<br><br>&nbsp; &nbsp; procedure OnMinimized;<br>&nbsp; &nbsp; procedure OnMaximized;<br>&nbsp; &nbsp; procedure OnRestored(resetmax : boolean);<br><br>&nbsp; &nbsp; function HookProc(var Msg : TMessage) : boolean;<br><br>&nbsp; protected<br>&nbsp; &nbsp; procedure Loaded; override;<br>&nbsp; &nbsp; { Protected declarations }<br>&nbsp; public<br>&nbsp; &nbsp; procedure SetItemState(itemID, state : Integer);<br>&nbsp; &nbsp; destructor Destroy; override;<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; published<br>&nbsp; &nbsp; { Published declarations }<br>&nbsp; end;<br><br>procedure Register;<br><br>implementation<br><br>procedure Register;<br>begin<br>&nbsp; RegisterComponents('Samples', [TStandardSystemMenu])<br>end;<br><br>{ TStandardSystemMenu }<br><br>procedure TStandardSystemMenu.CloneSystemMenu;<br>var<br>&nbsp; count : Integer;<br>&nbsp; item : TMenuItemInfo;<br>&nbsp; buffer : array [0..256] of char;<br>&nbsp; i : Integer;<br>begin<br>&nbsp; count := GetMenuItemCount(fMenuHandle);<br>&nbsp; while count &gt; 0 do<br>&nbsp; begin<br>&nbsp; &nbsp; DeleteMenu(fMenuHandle, 0, MF_BYPOSITION);<br>&nbsp; &nbsp; Dec(count)<br>&nbsp; end;<br><br>&nbsp; count := GetMenuItemCount(fWindowMenuHandle);<br><br>&nbsp; for i := 0 to count - 1 do<br>&nbsp; begin<br>&nbsp; &nbsp; FillChar(item, sizeof(item), 0);<br><br>&nbsp; &nbsp; if Win32MajorVersion &gt; 4 then &nbsp; &nbsp; &nbsp; // Ie Win2K or '98<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; item.cbSize := sizeof(item);<br>&nbsp; &nbsp; &nbsp; item.fMask := MIIM_STATE or MIIM_BITMAP or MIIM_ID or MIIM_STRING or MIIM_FTYPE;<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; item.cbSize := 44; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Sizeof old-style MENUITEMINFO<br>&nbsp; &nbsp; &nbsp; item.fMask := MIIM_STATE or MIIM_ID or MIIM_TYPE;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; item.cch := sizeof(buffer);<br>&nbsp; &nbsp; item.dwTypeData := buffer;<br><br>&nbsp; &nbsp; if GetMenuItemInfo(fWindowMenuHandle, i, True, item) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; case item.wID of<br>&nbsp; &nbsp; &nbsp; &nbsp; SC_RESTORE &nbsp;: item.wID := scxRestore;<br>&nbsp; &nbsp; &nbsp; &nbsp; SC_MINIMIZE : item.wID := scxMinimize;<br>&nbsp; &nbsp; &nbsp; &nbsp; SC_MAXIMIZE : item.wID := scxMaximize;<br>&nbsp; &nbsp; &nbsp; &nbsp; SC_MOVE &nbsp; &nbsp; : item.wID := scxMove;<br>&nbsp; &nbsp; &nbsp; &nbsp; SC_SIZE &nbsp; &nbsp; : item.wID := scxSize;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; InsertMenuItem(fMenuHandle, i, True, item)<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; RaiseLastOSError<br>&nbsp; end<br>end;<br><br>destructor TStandardSystemMenu.Destroy;<br>begin<br>&nbsp; Classes.FreeObjectInstance(fObjectInstance);<br>&nbsp; Classes.FreeObjectInstance(fSysObjectInstance);<br><br>&nbsp; inherited;<br>end;<br><br>function TStandardSystemMenu.HookProc(var Msg: TMessage): boolean;<br>var<br>&nbsp; LocalFlags: word;<br>begin<br>&nbsp; Result := false;<br>&nbsp; if Msg.Msg = WM_WindowPosChanging then<br>&nbsp; begin<br>&nbsp; &nbsp; with TWMWindowPosMsg(Msg).WindowPos^do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; if(hWnd = Application.Handle) and<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;not IsIconic(hWnd) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;and<br>&nbsp; &nbsp; &nbsp; &nbsp; (cx &gt; 0) and(cy &gt; 0) &nbsp; &nbsp; &nbsp; then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; LocalFlags := flags or SWP_NoZOrder;<br>&nbsp; &nbsp; &nbsp; &nbsp; if TForm(Owner).BorderStyle = bsSizeable then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LocalFlags := LocalFlags and not SWP_NoSize<br>&nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LocalFlags := LocalFlags or SWP_NoSize;<br>&nbsp; &nbsp; &nbsp; &nbsp; SetWindowPos(TForm(Owner).Handle, 0, x, y, cx, cy, LocalFlags);<br>&nbsp; &nbsp; &nbsp; &nbsp; TForm(Owner).Invalidate<br>&nbsp; &nbsp; &nbsp; end<br>&nbsp; &nbsp; end<br>&nbsp; end<br>end;<br><br>procedure TStandardSystemMenu.Loaded;<br>begin<br>&nbsp; inherited;<br>&nbsp; fMenuHandle := GetSystemMenu(Application.Handle, False);<br>&nbsp; fWindowMenuHandle := GetSystemMenu((Owner as TForm).Handle, False);<br>&nbsp; CloneSystemMenu;<br><br>&nbsp; fObjectInstance := Classes.MakeObjectInstance(OwnerWindowProc);<br>&nbsp; fOldOwnerWindowProc := TfnWndProc(SetWindowLong(TForm(Owner).Handle, GWL_WNDPROC, Integer(fObjectInstance)));<br><br>&nbsp; fSysObjectInstance := Classes.MakeObjectInstance(SysOwnerWindowProc);<br>&nbsp; fOldSysWindowProc := TfnWndProc(SetWindowLong(Application.Handle, GWL_WNDPROC, Integer(fSysObjectInstance)));<br><br>&nbsp; Application.HookMainWindow(HookProc);<br>end;<br><br>procedure TStandardSystemMenu.OnMaximized;<br>begin<br>&nbsp; fIconic := False;<br>&nbsp; fMaximized := True;<br>&nbsp; SetItemState(scxMinimize, MFS_ENABLED);<br>&nbsp; SetItemState(scxMaximize, MFS_DISABLED or MFS_GRAYED);<br>&nbsp; SetItemState(scxMove, &nbsp; &nbsp; MFS_DISABLED or MFS_GRAYED);<br>&nbsp; SetItemState(scxSize, &nbsp; &nbsp; MFS_DISABLED or MFS_GRAYED);<br>&nbsp; SetItemState(scxRestore, &nbsp;MFS_ENABLED);<br>end;<br><br>procedure TStandardSystemMenu.OnMinimized;<br>begin<br>&nbsp; fIconic := True;<br>&nbsp; SetItemState(scxMinimize, MFS_DISABLED or MFS_GRAYED);<br>&nbsp; SetItemState(scxMaximize, MFS_ENABLED);<br>&nbsp; SetItemState(scxMove, &nbsp; &nbsp; MFS_DISABLED or MFS_GRAYED);<br>&nbsp; SetItemState(scxSize, &nbsp; &nbsp; MFS_DISABLED or MFS_GRAYED);<br>&nbsp; SetItemState(scxRestore, &nbsp;MFS_ENABLED);<br>end;<br><br>procedure TStandardSystemMenu.OnRestored(resetmax : boolean);<br>begin<br>&nbsp; fIconic := False;<br>&nbsp; if resetmax then fMaximized := False;<br>&nbsp; if fMaximized then<br>&nbsp; &nbsp; OnMaximized<br>&nbsp; else<br>&nbsp; begin<br>&nbsp; &nbsp; SetItemState(scxMinimize, MFS_ENABLED);<br>&nbsp; &nbsp; SetItemState(scxMaximize, MFS_ENABLED);<br>&nbsp; &nbsp; SetItemState(scxMove, &nbsp; &nbsp; MFS_ENABLED);<br>&nbsp; &nbsp; SetItemState(scxSize, &nbsp; &nbsp; MFS_ENABLED);<br>&nbsp; &nbsp; SetItemState(scxRestore, &nbsp;MFS_DISABLED or MFS_GRAYED)<br>&nbsp; end<br>end;<br><br>procedure TStandardSystemMenu.OwnerWindowProc(var msg : TMessage);<br>begin<br>&nbsp; with msg do<br>&nbsp; begin<br>&nbsp; &nbsp; if msg = WM_SIZE then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; case wParam of<br>&nbsp; &nbsp; &nbsp; &nbsp; SIZE_MAXIMIZED : OnMaximized;<br>&nbsp; &nbsp; &nbsp; &nbsp; SIZE_MINIMIZED : OnMinimized;<br>&nbsp; &nbsp; &nbsp; &nbsp; SIZE_RESTORED &nbsp;: OnRestored(true)<br>&nbsp; &nbsp; &nbsp; end<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; if msg = WM_DESTROY then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; SetWindowLong(TForm(Owner).Handle, GWL_WNDPROC, Integer(fOldOwnerWindowProc));<br>&nbsp; &nbsp; &nbsp; &nbsp; SetWindowLong(Application.Handle, GWL_WNDPROC, Integer(fOldSysWindowProc));<br>&nbsp; &nbsp; &nbsp; &nbsp; Application.UnHookMainWindow(HookProc);<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; result := CallWindowProc(fOldOwnerWindowProc, TForm(Owner).Handle, msg, wParam, lParam)<br>&nbsp; end<br>end;<br><br>procedure TStandardSystemMenu.SetItemState(itemID, state: Integer);<br>var<br>&nbsp; item : TMenuItemInfo;<br>begin<br>&nbsp; FillChar(item, SizeOf(item), 0);<br>&nbsp; item.cbSize := 44;<br>&nbsp; item.fMask := MIIM_STATE;<br>&nbsp; if GetMenuItemInfo(fMenuHandle, itemID, False, item) then<br>&nbsp; begin<br>&nbsp; &nbsp; item.fState := state;<br>&nbsp; &nbsp; SetMenuItemInfo(fMenuHandle, itemID, False, item)<br>&nbsp; end<br>end;<br><br>procedure TStandardSystemMenu.SysOwnerWindowProc(var msg: TMessage);<br>var<br>&nbsp; m : Integer;<br>begin<br>&nbsp; with msg do<br>&nbsp; begin<br>&nbsp; &nbsp; if msg = WM_SYSCOMMAND then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; m := -1;<br>&nbsp; &nbsp; &nbsp; case wParam of<br>&nbsp; &nbsp; &nbsp; &nbsp; scxRestore &nbsp;:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m := SC_RESTORE;<br>&nbsp; &nbsp; &nbsp; &nbsp; scxMinimize :<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m := SC_MINIMIZE;<br>&nbsp; &nbsp; &nbsp; &nbsp; scxMaximize : if fMaximized then &nbsp;// It's also minimized, but it *was* maximized so restore!<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(Application.Handle, WM_SYSCOMMAND, SC_RESTORE, lParam)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if fIconic then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(Application.Handle, WM_SYSCOMMAND, SC_RESTORE, lParam);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(TForm(owner).Handle, WM_SYSCOMMAND, SC_MAXIMIZE, lParam);<br>{ SendMessage(TForm(owner).Handle, WM_SYSCOMMAND, SC_MAXIMIZE, lParam);}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br><br><br>&nbsp; &nbsp; &nbsp; &nbsp; scxMove &nbsp; &nbsp; : m := SC_MOVE;<br>&nbsp; &nbsp; &nbsp; &nbsp; scxSize &nbsp; &nbsp; : m := SC_SIZE;<br>&nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; &nbsp; if m &lt;&gt; -1 then<br>&nbsp; &nbsp; &nbsp; &nbsp; if fIconic then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(Application.Handle, WM_SYSCOMMAND, m, lParam)<br>&nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SendMessage(TForm(owner).Handle, WM_SYSCOMMAND, m, lParam);<br>&nbsp; &nbsp; end<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; if msg = WM_SIZE then<br>&nbsp; &nbsp; &nbsp; &nbsp; case wParam of<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SIZE_MAXIMIZED : OnMaximized;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SIZE_MINIMIZED : OnMinimized;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SIZE_RESTORED &nbsp;: OnRestored(false)<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; result := CallWindowProc(fOldSysWindowProc, Application.Handle, msg, wParam, lParam);<br>&nbsp; end<br>end;<br><br>end.<br><br><br>
 
这两天忙着项目小结,等星期六回杭州后再写些代码吧,也请pcexplorer别急着把帖子结掉.<br><br>我的思路是<br>1.把application的menuitem全部去掉,然后把form的system menuitem加上去(仅仅加上去文字)<br>2.定义六个用户自定义消息,对应加上去的menuitem,在自定义消息中对max,min,move等作处理.<br><br>不知道这种思路对不对.算了,等周末把代码写出来后再说吧.<br><br>不过我主要是想不通为什么要把form和application的系统菜单同步,这样做有什么好处?<br>费这么多精力,还不如看点别的东西.
 
thanks to bluerain! :)<br>你的思路基本上跟上面的代码一致。<br>我说的系统菜单同步指的是form最小(大)化的时候application也应该是最小(大)化<br>的状态,所以通常都需要对form和application同时处理以保证状态一致,否则时不时会<br>没有状态条,或者状态条出现了两个。<br><br>今天我又研究了一下,参考了一个老外的代码,总体思路是隐藏application菜单,显<br>示form菜单,在form的系统消息响应中同步application状态,零零碎碎总还是有些问题。<br>越发觉得borland能力不够。。。。。<br><br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br>&nbsp; Dialogs, StdCtrls, ComCtrls;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; OpenDialog1: TOpenDialog;<br>&nbsp; &nbsp; procedure FormShow(Sender: TObject);<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; protected<br>&nbsp; &nbsp; procedure WMACTIVATEAPP(var Msg: TWMACTIVATEAPP); message WM_ACTIVATEAPP;<br>&nbsp; &nbsp; procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;<br>&nbsp; &nbsp; procedure CreateParams(var Params: TCreateParams); override;<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br>uses commctrl;<br><br>{$R *.dfm}<br>procedure TForm1.CreateParams(var Params: TCreateParams);<br>begin<br>&nbsp; inherited;<br>&nbsp; Params.ExStyle:= Params.ExStyle or WS_EX_APPWINDOW;<br>end;<br><br>procedure TForm1.FormShow(Sender: TObject);<br>begin<br>&nbsp; ShowWindow(Application.Handle, SW_HIDE);<br>end;<br><br>procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);<br>begin<br>&nbsp; case Msg.CmdType of<br>&nbsp; &nbsp; SC_MINIMIZE: begin<br>// &nbsp; &nbsp; &nbsp;ShowWindow(Handle, SW_MINIMIZE);<br>(**) &nbsp;Application.Minimize;<br>(**) &nbsp;ShowWindow(Handle, SW_MINIMIZE);<br>(**) &nbsp;ShowWindow(Application.Handle, SW_HIDE);<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; SC_RESTORE: begin<br>&nbsp; &nbsp; &nbsp; if WindowState = wsMinimized then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; inherited;<br>&nbsp; &nbsp; &nbsp; &nbsp; exit;<br>&nbsp; &nbsp; &nbsp; end;<br>(**) &nbsp;Application.Restore;<br>&nbsp; &nbsp; &nbsp; ShowWindow(Handle, SW_RESTORE);<br>(**) &nbsp;ShowWindow(Application.Handle, SW_HIDE);<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; inherited;<br>&nbsp; end;<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br>&nbsp; OpenDialog1.Execute; &nbsp;//用来测试模态窗口的情况<br>end;<br><br>procedure TForm1.WMACTIVATEAPP(var Msg: TWMACTIVATEAPP);<br>begin<br>&nbsp; application.Dispatch(msg);<br>end;<br><br>end.<br>
 
to bluerain:<br>你怎么跟我一样,周末回杭州?
 
呵呵,我是因为老婆要生了,所以公司放我两周的假期.<br>所以这两天要拼命多做点事,争取五一也不回广州.<br>我现在在广州干活,Adnil不会也在广州吧,呵呵.
 
borland的大叔们为了大家方便,为每个应用程序封装了一个TApplication类,却忘了<br>两个重要的东西(其实这也不是一次两次了),与Microsoft的差距也可见一斑。<br>1、在Delphi 3.0和Delphi 4.0中,程序在最小化和还原的时候,窗口是瞬间消失的,<br>并没有象用VC或VB等开发工具编制的程序那样有动态的渐变效果(不过,在borland<br>意识到这个问题之后,Delphi 5.0中已经解决)。<br><br>2、Delphi的所有版本编制的程序,都无法和标准的Windows程序正常地排列平铺(这<br>一点才是最重要的)。<br><br>3、像pcexplorer说的“系统菜单和标准的不一样,太丑”。<br><br>4、在Windows程序中,Handle十个很重要的东西,而绝大多数Delphi程序,为了方便,<br>都是用Application的Handle作为ParentWindow,这与Microsoft的程序效果是不同的。<br>4、1装win2000和winXP的朋友可以试一下,打开资源管理器,在打开文件夹选项,然后<br>点击资源管理器的空白地方,“文件夹选项”窗口四周会闪动。<br>而在Delphi程序中,你就会发现,一般来说ShowModal的窗口是不会闪动的,因为Windows<br>找到的不是把它ShowModal出来的那个窗口的Handle,而是Application的Handle啊!<br>所以说VC编程要麻烦一些,到处Handle传过来传过去的。<br><br>4、2 Delphi程序中会出现这种情况:在主窗口中用API Messagebox(self.handle...)<br>显示一个对话框的时候,这个对话框对于主窗口来说是模式的,你不可能选中主窗口,<br>但在状态栏上却可以把主窗口最小化!是不是很奇怪?看看Windows,没有这种情况,<br>模式窗口就是模式窗口,不关闭它你不可能使主窗口获得焦点的,要在状态栏上把主<br>窗口最小化更是不可能。<br>——————————————————————————————————————<br>上面的朋友们给出了许多方法,却没有一个解决了这四个问题的。<br><br>其实,既然已经多了一个TApplication,再浪费一个Form又有何妨,就当是一个控件<br>不就行了?何况是为了追求界面。<br>——————————————————————————————————————<br>2001-7-3我就给出了解决方案,pcexplorer说是占用资源而且还没有解决问题,那是因<br>为他还使用delphi的传统方法来显示一个模式窗口。解决前三个问题看我的文章<br><br>http://eagleboost.myrice.com/issues/Materials/Articles/DelphiWindow.htm<br><br>最后一个问题需要用标准的Windows方法来解决,也就是使得ShowModal出来的窗口<br>的ParentWindowHandle就是把它ShowModal出来的那个窗口的handle,方法如下(假<br>设主窗口名为MainForm,子窗口名为subForm):<br>1、重载subForm的CreateParams方法。<br>2、在subForm的CreateParams方法中把Params.ParentWnd设置为MainForm.handle(<br>[red]这个Params很有用,你可以用它来修改类名!注意到了没有?)[/red]<br>3、在MainForm中建立subForm,再ShowModal,效果就出来了。<br><br>占用资源吗?当然!用控件不是一样占用资源吗!<br>——————————————————————————————————————<br>动态效果?没问题!<br>正常排列平铺?没问题!<br>美观?没问题!<br>标准?没问题!<br>——————————————————————————————————————<br>唯一的缺点,这个Params.ParentWnd需要你随时更改,尤其是好几个窗口都要ShowModal<br>同一个窗口的时候,但是实现没有问题的,想想看吧。<br>
 
我杭州人,在上海干活 :(
 
to CathyEagle:<br>按您的方法,通用的DIALOG,所有的子form都需要重写的,我觉得过于麻烦。特别是第三<br>方的东东可能就用不来了 ;)
 
原来是老乡,呵呵.<br>前面语句有点火(最近正好是做项目的烦躁期,在外地的各位应该都有体会),还请原谅.<br>我今年估计要留在广州干活了,还好公司对我还不错,可以时不时的溜回杭州过过小日子.<br>如果有空可以一起去喝喝茶,交流交流. DFW上应该还有不少杭州的,什么时候大家都聚<br>一下. 我的电话0571-88353477,有空联系.<br><br>关于CathyEagle提的Delphi的一些问题,例如2,早就觉得不舒服了,不过既然用的是Delphi,<br>也就只能将就了.<br>解决上述的问题的关键,我的感想是改动最好不要伤筋动骨,同时一定要确保稳定性.<br>如果任何方法不能达到这两点,丑陋一点就丑陋一点了.毕竟现在还是用Delphi做商业<br>开发的.稳定性和开发的时效性第一.<br><br>to CathyEagle:<br>十分感谢上了一课,回去后好好试验一下.<br>另外想问一下,你的方法有没有在比较大一点的应用程序上应用过,如果应用过了,<br>运行了多久没有问题.(虽然从感觉上应该没有问题,但是总想确认一下,呵呵).
 
后退
顶部