메뉴에 컨트롤넣기 - 양병규

From YYpBD's MediaWiki

Jump to: navigation, search


양병규가 맹근 방법입니다..........  
내려받기 : 메뉴에_콘트롤_넣기.ZIP (136318 바이트)

메뉴에다가 콘트롤을 집어넣으려면...

크게 두 가지 방법이 있을 수 있겠죠...

SetParent를 이용해서 콘트롤을 진짜로 메뉴에다가 쳐넣는 방법이 있겠고...

메뉴의 OwnerDraw를 이용해서 콘트롤을 그려주는 방법이 있을 수 있겠습니다.

물론 그 외에도 여러가지 방법은 있을수 있을겁니다. 예컨데...

메뉴도 윈도우니깐 SetWindowLong를 이용해서 스타일을 바꿀수도 있겠고여....

암튼....

이것 저것 다 해봤는데(이걸 왜 했지? --;)

그 중에 젤루 맘에 드는게 두번째 방법인 OwnerDraw가 가장 손쉽고 그나마 조금 깔끔합니다.

깜빡임이 있기는한데 이것은 메뉴윈도를 서브클래싱해서 페인팅메세지를 조금 처리하면 될것같습니다.


콘트롤을 메뉴에 그려넣고 마우스 동작을 하게 하려면....


첫째, 마우스를 클릭해도 메뉴가 닫히기 않게 하기.

둘째, 메뉴의 크기를 콘트롤의 크기와 같게 하기.

셋째, 메뉴에 콘트롤을 그려넣기.

넷째, 메뉴에 마우스가 접근했을때를 인식하기.

다섯째, 메뉴위에서 마우스가 클릭되고 이동하는것을 인식하기.

여섯째, 메뉴에서의 마우스 움직임을 콘트롤에게 전달하기.


이 정도만 해결이 되면 이것들을 잘 조합하면 되겠지요...

그럼 하나씩...

우선

첫째, 마우스를 클릭해도 메뉴가 닫히기 않게 하려면..

간단합니다. 메뉴아이템의 Enabled를 False로 하거나 메뉴아이템에 서브메뉴를 하나 만들어놓고 서브메뉴의 Visible를 False로 해서 안보이게 해도 되고여 메뉴아이템의 캡션을 '-'로 해도(아시죠?) 메뉴는 클릭이 되도 닫히지 않습니다.(완죤 변태에 가깝군여 ^^)

둘째, 메뉴의 크기를 콘트롤의 크기와 같게 하려면 메뉴아이템의 OnMeasureItem 이벤트를 이용하면 됩니다. 이 이벤트 핸들러의 vart Width, Height: Integer 이 파라미터에 값을 넣어주면 메뉴아이템은 그 크기로 바뀝니다. 물론 Width는 가장 큰 메뉴의 크기로 되겠지만요..

셋째, 메뉴에 콘트롤을 그려넣기도 간단합니다. TControl에는 PaintTo라는 메소드가 있습니다. 메뉴아이템의 OnDrawItem 이벤트에서 TrackBar1.PaintTo( ACanvas.Handle, ARect.Left, ARect.Top ); 하면 메뉴에 콘트롤이 그려집니다.

넷째, 메뉴에 마우스가 접근했을때를 인식하기는 이벤트에 없습니다. 폼의 메세지를 핸들링해야합니다. 메뉴에 마우스가 접근하면 폼(Form1)에 WM_MENUSELECT 메세지가 발생합니다.

procedure TForm1.WMMenuSelect( var Message: TWMMenuSelect );
begin
inherited;
SelMenuCmd := Message.IDItem;//요렇게 메뉴아이템의 Command를 저장해 둡니다. Command는 일종의 메뉴아이템들의 ID와 같습니다.
end;

다섯째, 메뉴위에서 마우스가 클릭되고 이동하는것을 인식하려면 마찬가지로 폼의 메세지를 핸들링합니다. WM_ENTERIDLE 메세지를 처리하면됩니다. 메뉴에서 마우스가 이동할때마다 이 메세지가 발생합니다. 또한 메세지 스트럭쳐인 TWMEnterIdle에는 IdleWnd필드가 있는데 이넘은 메뉴의 윈도우핸들입니다.

여섯째, 메뉴에서의 마우스 움직임을 콘트롤에게 전달하는건 알아서 하세여 SendMessage로 날리던, 집어던지던 --;

이걸로 끝. 나머지는 소스를 함 읽어보시면 알수있을겁니다.





unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ImgList, Menus, ExtCtrls, AppEvnts, StdCtrls, ComCtrls, ToolWin;

type
TForm1 = class(TForm)
   Label1: TLabel;
   Label2: TLabel;
   MainMenu1: TMainMenu;
   Menu_Exit: TMenuItem;
   Menu_File: TMenuItem;
   Menu_New: TMenuItem;
   Menu_Open: TMenuItem;
   Menu_Options: TMenuItem;
   Menu_PageControl: TMenuItem;
   Menu_Save: TMenuItem;
   Menu_Split1: TMenuItem;
   Menu_Split2: TMenuItem;
   Menu_TrackBar: TMenuItem;
   PageControl1: TPageControl;
   TabSheet1: TTabSheet;
   TabSheet2: TTabSheet;
   ToolbarImages: TImageList;
   TrackBar1: TTrackBar;
   Menu_CustomStyle: TMenuItem;
   procedure Menu_TrackBarMeasureItem(Sender: TObject; ACanvas: TCanvas; var Width, Height: Integer);
   procedure Menu_TrackBarDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect; Selected: Boolean);

   procedure Menu_PageControlDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect; Selected: Boolean);
   procedure Menu_PageControlMeasureItem(Sender: TObject; ACanvas: TCanvas; var Width, Height: Integer);
private
   ControlMenuClick: Boolean;
   SelMenuCmd: Integer;
   SelMenuWnd: HWnd;

   procedure WMMenuSelect( var Message: TWMMenuSelect ); message WM_MENUSELECT;
   procedure WMEnterIdle( var Message: TWMEnterIdle ); message WM_ENTERIDLE;

   procedure MenuTrackBarMouseDown( X, Y: Integer );
   procedure MenuTrackBarMouseMove( X, Y: Integer );
   procedure MenuTrackBarMouseDrag( X, Y: Integer );
   procedure MenuTrackBarMouseUp( X, Y: Integer );

   procedure MenuPageControlMouseDown( X, Y: Integer );
   procedure MenuPageControlMouseMove( X, Y: Integer );
   procedure MenuPageControlMouseDrag( X, Y: Integer );
   procedure MenuPageControlMouseUp( X, Y: Integer );
public
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function IsMouseDown: Boolean;
begin
Result := GetAsyncKeyState( 1 ) <> 0;
end;

function WindowMousePos( Wnd: HWnd ): TPoint;
var
ARect: TRect;
begin
GetWindowRect( Wnd, ARect );
Result := Point( Mouse.CursorPos.X - ARect.Left, Mouse.CursorPos.X - ARect.Top );
end;

procedure RedrawMenuItem( MenuItem: TMenuItem );
begin
MenuItem.Enabled := True;
MenuItem.Enabled := False;
end;

function MousePosToTrackBarPos( TrackBar: TTrackBar; X: Integer ): Integer;
begin
Result := Round( ( X / TrackBar.Width ) * TrackBar.Max );
end;

{Menu Message Handlers}

procedure TForm1.WMMenuSelect( var Message: TWMMenuSelect );
begin
inherited;
SelMenuCmd := Message.IDItem;
end;

procedure TForm1.WMEnterIdle( var Message: TWMEnterIdle );
var
X, Y: Integer;
begin
inherited;

SelMenuWnd := Message.IdleWnd;

X := WindowMousePos( SelMenuWnd ).X;
Y := WindowMousePos( SelMenuWnd ).Y;

if IsMouseDown then
  begin
    if ControlMenuClick then
     begin
       if SelMenuCmd = Menu_TrackBar.Command then MenuTrackBarMouseDrag( X, Y ) else
       if SelMenuCmd = Menu_PageControl.Command then MenuPageControlMouseDrag( X, Y );
     end
    else
     begin
       ControlMenuClick := True;
       if SelMenuCmd = Menu_TrackBar.Command then MenuTrackBarMouseDown( X, Y ) else
       if SelMenuCmd = Menu_PageControl.Command then MenuPageControlMouseDown( X, Y );
     end;
  end
else
  begin
    if ControlMenuClick then
     begin
       ControlMenuClick := False;
       if SelMenuCmd = Menu_TrackBar.Command then MenuTrackBarMouseUp( X, Y ) else
       if SelMenuCmd = Menu_PageControl.Command then MenuPageControlMouseUp( X, Y );
     end
    else
     begin
       if SelMenuCmd = Menu_TrackBar.Command then MenuTrackBarMouseMove( X, Y ) else
       if SelMenuCmd = Menu_PageControl.Command then MenuPageControlMouseMove( X, Y );
     end;
  end;
end;

{Menu_TrackBar Event Handlers}

procedure TForm1.Menu_TrackBarMeasureItem(Sender: TObject; ACanvas: TCanvas; var Width, Height: Integer);
begin
Width := TrackBar1.Width - 14;
Height := TrackBar1.Height;
end;

procedure TForm1.Menu_TrackBarDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect; Selected: Boolean);
begin
TrackBar1.PaintTo( ACanvas.Handle, ARect.Left, ARect.Top );
end;

procedure TForm1.MenuTrackBarMouseDown( X, Y: Integer );
begin

end;

procedure TForm1.MenuTrackBarMouseMove( X, Y: Integer );
begin

end;

procedure TForm1.MenuTrackBarMouseDrag( X, Y: Integer );
begin
TrackBar1.Position := MousePosToTrackBarPos( TrackBar1, X - 2 );
RedrawMenuItem( Menu_TrackBar );
end;

procedure TForm1.MenuTrackBarMouseUp( X, Y: Integer );
begin

end;

{Menu_PageControl Event Handlers}

procedure TForm1.Menu_PageControlDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect; Selected: Boolean);
begin
PageControl1.PaintTo( ACanvas.Handle, ARect.Left, ARect.Top );
end;

procedure TForm1.Menu_PageControlMeasureItem(Sender: TObject; ACanvas: TCanvas; var Width, Height: Integer);
begin
Width := PageControl1.Width - 14;
Height := PageControl1.Height;
end;

procedure TForm1.MenuPageControlMouseDown( X, Y: Integer );
begin
SendMessage( PageControl1.Handle, WM_LBUTTONDOWN, MK_LBUTTON, MakeLong( X, 5 ) );
RedrawMenuItem( Menu_PageControl );
end;

procedure TForm1.MenuPageControlMouseMove( X, Y: Integer );
begin

end;

procedure TForm1.MenuPageControlMouseDrag( X, Y: Integer );
begin

end;

procedure TForm1.MenuPageControlMouseUp( X, Y: Integer );
begin

end;


맞춤검색