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> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus;<br><br>const<br> scxRESTORE = $fff0;<br> scxMINIMIZE = $fff2;<br> scxMAXIMIZE = $fff3;<br> scxSIZE = $fff4;<br> scxMOVE = $fff5;<br><br>type<br> TStandardSystemMenu = class(TComponent)<br> private<br> fMenuHandle : HMenu;<br> fWindowMenuHandle : HMenu;<br> fObjectInstance : pointer;<br> fOldOwnerWindowProc : TFNWndProc;<br><br> fSysObjectInstance : pointer;<br> fOldSysWindowProc : TFNWndProc;<br><br> fIconic : boolean;<br> fMaximized : boolean;<br><br> procedure CloneSystemMenu;<br> procedure OwnerWindowProc(var msg: TMessage);<br> procedure SysOwnerWindowProc(var msg: TMessage);<br><br> procedure OnMinimized;<br> procedure OnMaximized;<br> procedure OnRestored(resetmax : boolean);<br><br> function HookProc(var Msg : TMessage) : boolean;<br><br> protected<br> procedure Loaded; override;<br> { Protected declarations }<br> public<br> procedure SetItemState(itemID, state : Integer);<br> destructor Destroy; override;<br> { Public declarations }<br> published<br> { Published declarations }<br> end;<br><br>procedure Register;<br><br>implementation<br><br>procedure Register;<br>begin<br> RegisterComponents('Samples', [TStandardSystemMenu])<br>end;<br><br>{ TStandardSystemMenu }<br><br>procedure TStandardSystemMenu.CloneSystemMenu;<br>var<br> count : Integer;<br> item : TMenuItemInfo;<br> buffer : array [0..256] of char;<br> i : Integer;<br>begin<br> count := GetMenuItemCount(fMenuHandle);<br> while count > 0 do<br> begin<br> DeleteMenu(fMenuHandle, 0, MF_BYPOSITION);<br> Dec(count)<br> end;<br><br> count := GetMenuItemCount(fWindowMenuHandle);<br><br> for i := 0 to count - 1 do<br> begin<br> FillChar(item, sizeof(item), 0);<br><br> if Win32MajorVersion > 4 then // Ie Win2K or '98<br> begin<br> item.cbSize := sizeof(item);<br> item.fMask := MIIM_STATE or MIIM_BITMAP or MIIM_ID or MIIM_STRING or MIIM_FTYPE;<br> end<br> else<br> begin<br> item.cbSize := 44; // Sizeof old-style MENUITEMINFO<br> item.fMask := MIIM_STATE or MIIM_ID or MIIM_TYPE;<br> end;<br> item.cch := sizeof(buffer);<br> item.dwTypeData := buffer;<br><br> if GetMenuItemInfo(fWindowMenuHandle, i, True, item) then<br> begin<br> case item.wID of<br> SC_RESTORE : item.wID := scxRestore;<br> SC_MINIMIZE : item.wID := scxMinimize;<br> SC_MAXIMIZE : item.wID := scxMaximize;<br> SC_MOVE : item.wID := scxMove;<br> SC_SIZE : item.wID := scxSize;<br> end;<br> InsertMenuItem(fMenuHandle, i, True, item)<br> end<br> else<br> RaiseLastOSError<br> end<br>end;<br><br>destructor TStandardSystemMenu.Destroy;<br>begin<br> Classes.FreeObjectInstance(fObjectInstance);<br> Classes.FreeObjectInstance(fSysObjectInstance);<br><br> inherited;<br>end;<br><br>function TStandardSystemMenu.HookProc(var Msg: TMessage): boolean;<br>var<br> LocalFlags: word;<br>begin<br> Result := false;<br> if Msg.Msg = WM_WindowPosChanging then<br> begin<br> with TWMWindowPosMsg(Msg).WindowPos^do<br> begin<br> if(hWnd = Application.Handle) and<br> not IsIconic(hWnd) and<br> (cx > 0) and(cy > 0) then<br> begin<br> LocalFlags := flags or SWP_NoZOrder;<br> if TForm(Owner).BorderStyle = bsSizeable then<br> LocalFlags := LocalFlags and not SWP_NoSize<br> else<br> LocalFlags := LocalFlags or SWP_NoSize;<br> SetWindowPos(TForm(Owner).Handle, 0, x, y, cx, cy, LocalFlags);<br> TForm(Owner).Invalidate<br> end<br> end<br> end<br>end;<br><br>procedure TStandardSystemMenu.Loaded;<br>begin<br> inherited;<br> fMenuHandle := GetSystemMenu(Application.Handle, False);<br> fWindowMenuHandle := GetSystemMenu((Owner as TForm).Handle, False);<br> CloneSystemMenu;<br><br> fObjectInstance := Classes.MakeObjectInstance(OwnerWindowProc);<br> fOldOwnerWindowProc := TfnWndProc(SetWindowLong(TForm(Owner).Handle, GWL_WNDPROC, Integer(fObjectInstance)));<br><br> fSysObjectInstance := Classes.MakeObjectInstance(SysOwnerWindowProc);<br> fOldSysWindowProc := TfnWndProc(SetWindowLong(Application.Handle, GWL_WNDPROC, Integer(fSysObjectInstance)));<br><br> Application.HookMainWindow(HookProc);<br>end;<br><br>procedure TStandardSystemMenu.OnMaximized;<br>begin<br> fIconic := False;<br> fMaximized := True;<br> SetItemState(scxMinimize, MFS_ENABLED);<br> SetItemState(scxMaximize, MFS_DISABLED or MFS_GRAYED);<br> SetItemState(scxMove, MFS_DISABLED or MFS_GRAYED);<br> SetItemState(scxSize, MFS_DISABLED or MFS_GRAYED);<br> SetItemState(scxRestore, MFS_ENABLED);<br>end;<br><br>procedure TStandardSystemMenu.OnMinimized;<br>begin<br> fIconic := True;<br> SetItemState(scxMinimize, MFS_DISABLED or MFS_GRAYED);<br> SetItemState(scxMaximize, MFS_ENABLED);<br> SetItemState(scxMove, MFS_DISABLED or MFS_GRAYED);<br> SetItemState(scxSize, MFS_DISABLED or MFS_GRAYED);<br> SetItemState(scxRestore, MFS_ENABLED);<br>end;<br><br>procedure TStandardSystemMenu.OnRestored(resetmax : boolean);<br>begin<br> fIconic := False;<br> if resetmax then fMaximized := False;<br> if fMaximized then<br> OnMaximized<br> else<br> begin<br> SetItemState(scxMinimize, MFS_ENABLED);<br> SetItemState(scxMaximize, MFS_ENABLED);<br> SetItemState(scxMove, MFS_ENABLED);<br> SetItemState(scxSize, MFS_ENABLED);<br> SetItemState(scxRestore, MFS_DISABLED or MFS_GRAYED)<br> end<br>end;<br><br>procedure TStandardSystemMenu.OwnerWindowProc(var msg : TMessage);<br>begin<br> with msg do<br> begin<br> if msg = WM_SIZE then<br> begin<br> case wParam of<br> SIZE_MAXIMIZED : OnMaximized;<br> SIZE_MINIMIZED : OnMinimized;<br> SIZE_RESTORED : OnRestored(true)<br> end<br> end<br> else<br> if msg = WM_DESTROY then<br> begin<br> SetWindowLong(TForm(Owner).Handle, GWL_WNDPROC, Integer(fOldOwnerWindowProc));<br> SetWindowLong(Application.Handle, GWL_WNDPROC, Integer(fOldSysWindowProc));<br> Application.UnHookMainWindow(HookProc);<br> end;<br> result := CallWindowProc(fOldOwnerWindowProc, TForm(Owner).Handle, msg, wParam, lParam)<br> end<br>end;<br><br>procedure TStandardSystemMenu.SetItemState(itemID, state: Integer);<br>var<br> item : TMenuItemInfo;<br>begin<br> FillChar(item, SizeOf(item), 0);<br> item.cbSize := 44;<br> item.fMask := MIIM_STATE;<br> if GetMenuItemInfo(fMenuHandle, itemID, False, item) then<br> begin<br> item.fState := state;<br> SetMenuItemInfo(fMenuHandle, itemID, False, item)<br> end<br>end;<br><br>procedure TStandardSystemMenu.SysOwnerWindowProc(var msg: TMessage);<br>var<br> m : Integer;<br>begin<br> with msg do<br> begin<br> if msg = WM_SYSCOMMAND then<br> begin<br> m := -1;<br> case wParam of<br> scxRestore :<br> m := SC_RESTORE;<br> scxMinimize :<br> m := SC_MINIMIZE;<br> scxMaximize : if fMaximized then // It's also minimized, but it *was* maximized so restore!<br> SendMessage(Application.Handle, WM_SYSCOMMAND, SC_RESTORE, lParam)<br> else<br> begin<br> if fIconic then<br> SendMessage(Application.Handle, WM_SYSCOMMAND, SC_RESTORE, lParam);<br> SendMessage(TForm(owner).Handle, WM_SYSCOMMAND, SC_MAXIMIZE, lParam);<br>{ SendMessage(TForm(owner).Handle, WM_SYSCOMMAND, SC_MAXIMIZE, lParam);}<br> end;<br><br><br> scxMove : m := SC_MOVE;<br> scxSize : m := SC_SIZE;<br> end;<br><br> if m <> -1 then<br> if fIconic then<br> SendMessage(Application.Handle, WM_SYSCOMMAND, m, lParam)<br> else<br> SendMessage(TForm(owner).Handle, WM_SYSCOMMAND, m, lParam);<br> end<br> else<br> if msg = WM_SIZE then<br> case wParam of<br> SIZE_MAXIMIZED : OnMaximized;<br> SIZE_MINIMIZED : OnMinimized;<br> SIZE_RESTORED : OnRestored(false)<br> end;<br><br> result := CallWindowProc(fOldSysWindowProc, Application.Handle, msg, wParam, lParam);<br> end<br>end;<br><br>end.<br><br><br>