delphi4arab منتديات دلفي للعرب
Menu Icon – VCL Style - نسخة قابلة للطباعة

+- delphi4arab منتديات دلفي للعرب (https://delphi4arab.net/forum)
+-- قسم : منتديات دلفي للعرب التعليمية (https://delphi4arab.net/forum/forumdisplay.php?fid=3)
+--- قسم : دروس دلفي للمبتدئين (https://delphi4arab.net/forum/forumdisplay.php?fid=13)
+--- الموضوع : Menu Icon – VCL Style (/showthread.php?tid=4580)



Menu Icon – VCL Style - SMP3 - 28-09-2012

السلام عليكم و رحمة الله وبركاته
سنتكلم في هذا الموضوع حول دعم ال Menu Icon ل VCL Style .
ال Menu Icon هي تلك القائمة المنبثقة التي تظهر بمجرد النقر على الأيقونة في أعلى الفورم
[صورة: iconmenu0.png]
لكن للأسف فكما تلاحظ فهو لا يدعم مكتبة ال VCL Style و لا يتوافق معها ,وهذا شيئ يؤثر على UI , سنرى في هذا الدرس الطريقة الملائمة لعمل التوافقية

قد تبدوا الفكرة من الوهلة الأولى صعبة لكنها جد سهلة و لم تأخذ من وقتي سوى نصف ساعة على انجازها
نبدأ على بركة الله

أولا عليك أن تفهم آلية العمل أو بالأحرى كيف يظهر ال Menu Icon ؟
يظهر بطريقتين : الأولى التوجه الى الأيقونة و الضغط بالزر الأيسر للماوس على الأيقونة
أما الثانية عن طريق الضغط بالزر الأيمن على ال Caption Bar
أي كلا الطريقتين تعتمد على النقر على ال Caption Bar

أضف PopupActionBar الى الفورم و أضف له 7 Items
[صورة: items7o.png]
نقوم باضافة هذه الاجراءات
PHP كود :
procedure TWMNCRBUTTONDOWN(var Msg: TWMNCRBUTTONDOWN ); message WM_NCRBUTTONDOWN ;
procedure TWMNCLBUTTONDOWN(var Msg: TWMNCLBUTTONDOWN ); message WM_NCLBUTTONDOWN ; 
و لا تنسى ارفاق المكتبة Vcl.Themes الى المشروع
PHP كود :
uses Vcl.Themes; 
الاجراء TWMNCLBUTTONDOWN ينفذ عند النقر بالزر الأيسر على ال Non Client Area
الاجراء TWMNCRBUTTONDOWN ينفذ عند النقر بالزر الأيمن على ال Non Client Area
PHP كود :
procedure TMain.TWMNCLBUTTONDOWN(var Msg: TWMNCLBUTTONDOWN );

var 
rPos:Tpoint;
WinRect:Trect;
ThemeDetails :TThemedElementDetails ;
sSizeFrameRight,sSizeCaptionBar:TSize;
sStyle:TStyleManager;
IconRect:TRECt;

begin

sStyle
:=TStyleManager.Create ;
// Check if Style is not Windows system style
if sStyle.ActiveStyle.IsSystemStyle then begin
sStyle
.Free ;
inherited;
exit;

end;

GetWindowRect(handle,WinRect);
WinApi.Windows.GetCursorPos(rPos); // Find cursor position on screen
ThemeDetails:=sStyle.ActiveStyle.GetElementDetails
( vcl.Themes.TThemedWindow.twFrameRightActive );// Get some information about window frame .
sStyle.ActiveStyle.GetElementSize
(0,ThemeDetails,TElementSize.esActual ,sSizeFrameRight);//Get Size of Window Frame
ThemeDetails:=sStyle.ActiveStyle.GetElementDetails ( vcl.Themes.TThemedWindow.twCaptionActive );
sStyle.ActiveStyle.GetElementSize(0,ThemeDetails,TElementSize.esActual ,sSizeCaptionBar);
IconRect := Rect(0, 0, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); // Get Icon Rectangle on window
sStyle.Free ;
// Check if cursor position

if (rPos.X-WinRect.Location.X )< sSizeFrameRight.Width then begin
inherited
;
exit;

end;

// Check is cursor is on window icon
if (rPos.X-WinRect.Location.X )< IconRect.Width*2 then
self
.PopupActionBar1.Popup(left+sSizeFrameRight.Width,top+sSizeCaptionBar.Height )else
inherited;
Msg.Result :=1;
end; 
الفكرة تعتمد على معرفة مكان الماوس , اذا المستخدم ضغط على ال Caption Bar يتم التحقق ما اذا كان موقع الماوس على الأيقونة الخاصة بالفورم , اذا تحقق الشرط يتم اظهار ال Menu
أما اذا لم يتحقق فيتم الخروج من الاجراء و اكمال السير العادي للبرنامج .
PHP كود :
procedure TMain.TWMNCRBUTTONDOWN(var Msg: TWMNCRBUTTONDOWN );

var 
rPos:Tpoint;
ThemeDetails :TThemedElementDetails ;
sSize:TSize;
sStyle:TStyleManager;
WinRect:Trect;

begin

WinApi
.Windows.GetCursorPos(rPos);
sStyle:=TStyleManager.Create ;
if 
sStyle.ActiveStyle.IsSystemStyle then begin
sStyle
.Free ;
inherited;
exit;

end;

ThemeDetails:=sStyle.ActiveStyle.GetElementDetails ( vcl.Themes.TThemedWindow.twCaptionActive );
sStyle.ActiveStyle.GetElementSize(0,ThemeDetails,TElementSize.esActual ,sSize);
sStyle.Free ;
GetWindowRect(handle,WinRect);
// Check if cursor is on Caption bar
if rPos.Y -WinRect.Location.Y <sSize.Height then
self
.PopupActionBar1 .Popup(rPos.x,rPos.Y )else
inherited;
end; 
الآن شغل البرنامج و جرب , أكيد لقد تم تغيير الستايل و أصبح متوافق مع ال Vcl Style , لكن ال Menu يحتةي على أسماء بعنواين Items 1..Items7
تستطيع تغيير هذه الاسماء , كما تستطيع أن تستخدم الاعدادت الخاصة بالجهاز

تابع معي
أضف هذه الاجراءات الى القسم Private
PHP كود :
procedure EnumMenus;

procedure ItemClick(Sender: TObject); 

الاجراء EnumMenus
PHP كود :
procedure TMain.EnumMenus;

var 
SysMenu:HMenu;
s:PAnsiChar;
icount:integer;
i: Integer;
rPos:TPoint;

begin

SysMenu 
:= GetSystemMenu(Handle, FALSE) ; // get handle to Menu Icon
icount:=WinApi.Windows.GetMenuItemCount(SysMenu);// Get Menu Count
for I := 0 to icount-1 do begin
GetMem
(s,256);
GetMenuStringA(SysMenu,i,s,-1,MF_BYPOSITION );// Get MenuItem Name
self.PopupActionBar1.Items[i].Caption :=s;
Self.PopupActionBar1.Items [i].OnClick :=ItemClick;
if 
s='' then
self
.PopupActionBar1.Items[i].Caption :='-';// Add Separator
FreeMem(s,256);
end;

end; 
يقوم هذا الاجراء بأخذ أسماء ال Menu Item الافتراضية الخاصة بالجهاز و استخدامها
PHP كود :
procedure TMain.ItemClick(Sender: TObject);

var 
SysMenu:HMenu;
MenuID:DWORD;

begin

SysMenu 
:= GetSystemMenu(Handle, FALSE) ;
MenuID:=WinApi.Windows.GetMenuItemID(SysMenu,TMenuItem(sender).MenuIndex) ;//Get ID
SendMessage(Handle,Winapi.Messages.WM_SYSCOMMAND ,MenuID ,0);//click MenuItem

end; 
الحدث ItemClick ينفذ عند الضغط على ال Menu
النتيجة
[صورة: iconmenu1.png]
كما يمكنك أن تتجاهل الحدث EnumMenus و تصمم ال Menu الخاص بك
[صورة: iconmenu2.png]


Menu Icon – VCL Style - مازن الاسماعيلي - 02-01-2013

شرح رائع وجميل بالتوفيق