작업표시줄에 메뉴를 내맘대로 조정하려면..
Applicaiton->Handle로 GetSystemMenu 해서 .. 처리해야 한다.
그렇게 하지 않고 좀더 쉽게 ..
TPopupMenu를 SystemMenu대신 띄우도록 하는 방법입니다.
원리는..
1. Application을 SubClassing해서요
2. TrackBar에 메뉴를 띄우라는 메세지를 잡어서 ...
3. TPopupmenu를 해당 위치에 띄우는것입니다.
컴포넌트
이것을 누가 컴포넌트로 이미 만들어 뒀더군요
http://delphi.about.com/od/vclwriteenhance/a/ttaskbarmenu.htm
그런데 저걸 굳이 컴포넌트화 까지 할 필요가 있나 싶어서
그냥 C++Builder로 변환해 보았습니다.
const int WM_TASKBAR_MENU = 0x0313; // magic!
void *oldWndProc;
void *newWndProc;
void __fastcall TForm1::FormCreate(TObject *Sender)
{
oldWndProc =(void *) GetWindowLong(Application->Handle, GWL_WNDPROC) ;
newWndProc = (void *)MakeObjectInstance(AppMessage) ;
SetWindowLong(Application->Handle, GWL_WNDPROC, LPARAM(newWndProc)) ;
}
void __fastcall TForm1::AppMessage(TMessage &Msg)
{
if(Msg.Msg==WM_TASKBAR_MENU)
{
PostMessage(Application->Handle,WM_POPUP_MENU,0,0);
return;
}
else if(Msg.Msg==WM_POPUP_MENU)
{
TPoint pt;
GetCursorPos(&pt);
PopupMenu1->Popup(pt.x,pt.y);
}
else
{
Msg.Result = CallWindowProc((FARPROC)oldWndProc, Application->Handle, Msg.Msg, Msg.WParam, Msg.LParam) ;
}
}
[TTaskBarMenu 컴포넌트 소스]
참조하세요
unit TaskBarMenu;
interface
uses
SysUtils, Classes, Menus, Messages, Windows, Forms, Controls;
type
TTaskBarMenu = class(TPopupMenu)
private
hookHandle : THandle;
oldWndProc: Pointer;
newWndProc: Pointer;
protected
procedure Hook;
procedure UnHook;
procedure AppWndProc(var Msg: TMessage) ;
public
constructor Create(AOwner: TComponent) ; override;
destructor Destroy; override;
end;
procedure Register;
implementation
const
WM_TASKBAR_MENU = $0313; // magic!
WM_POPUP_MENU = WM_USER + 1; //custom message
var
thisOnce : TTaskBarMenu = nil;
procedure Register;
begin
RegisterComponents('delphi.about.com', [TTaskBarMenu]) ;
end;
{ TTaskBarMenu }
procedure TTaskBarMenu.AppWndProc(var Msg: TMessage) ;
begin
case Msg.Msg of
WM_TASKBAR_MENU: PostMessage(hookHandle, WM_POPUP_MENU, 0, 0) ;
WM_POPUP_MENU: Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y) ;
else
Msg.Result := CallWindowProc(oldWndProc, hookHandle, Msg.Msg, Msg.wParam, Msg.lParam) ;
end;
end; (*AppWndProc*)
constructor TTaskBarMenu.Create(AOwner: TComponent) ;
begin
if Assigned(thisOnce) then
begin
raise Exception.Create('Only one instance of this component can be used per application!') ;
end
else
begin
inherited;
thisOnce := self;
hookHandle := Application.Handle;
Hook;
end;
end; (*Create*)
destructor TTaskBarMenu.Destroy;
begin
thisOnce := nil;
UnHook;
inherited;
end; (*Destroy*)
procedure TTaskBarMenu.Hook;
begin
oldWndProc := Pointer(GetWindowLong(hookHandle, GWL_WNDPROC)) ;
newWndProc := Classes.MakeObjectInstance(AppWndProc) ;
if not (csDesigning in ComponentState) then SetWindowLong(hookHandle, GWL_WNDPROC, longint(newWndProc)) ;
end; (*Hook*)
procedure TTaskBarMenu.UnHook;
begin
SetWindowLong(hookHandle, GWL_WNDPROC, longint(oldWndProc)) ;
if Assigned(newWndProc) then Classes.FreeObjectInstance(newWndProc) ;
NewWndProc := nil;
end; (*UnHook*)
end.
그럼..