26-09-2013, 12:50 PM
السلام عليكم و رحمة الله و بركاته
انتهيت للتو من مشروع كنت قد بدأته منذ أسبوع TThemedSysControls
على غرار مكونات المكونات التجارية Alpha Skin , BusinessSkinForm , تعد ال VCL Style من أفضلهم ..
لكون أن أحداث و رسائل النظام ترسل بطريقة مرنة غير عشوائية ..
لكن مع الأسف مكونات VCL Style لا تدعم المكونات القياسية الخاصة بالنظام :
System Menu , PopupMenu, OpenDialog,SaveDialog,ColorDialog,FontDialog,PrintDialog,FindDialog,ReplaceDialog,PageSetupDialog,MessageBox , ... و القائمة طويلة ..
![[صورة: CJyBZ.png]](http://im34.gulfup.com/CJyBZ.png)
كود :
http://im37.gulfup.com/dDS4k.pngالسبب في عدم دعم هذه المكونات هو أن جميع هذه المكونات يتدخل النظام في رسمها , ومحاولة التعديل عليها صعبة للغاية تتطلب فهم عميق لأغلب رسائل النظام ومتى يتم ارسالها و متى لا يتم ارسالها ..
اضافة الى ذلك مايكروسوفت جعلت من الأمر شبه مستحيل للتعديل على بعض المكونات , مثل المكون PopupMenu : كل شيئ مبهم حول هذا المكون حتى الرسائل التي يرسلها النظام للمكون غير موثقة لدى موقع المطورين MSDN (Undocumented Windows Messages) .
TThemedSysControls : مشروع لدعم كل هذه النقائص , و جعل مكونات النظام متناسقة مع مظهر ال VCL Style .
لا أخفيكم الأمر : لقد حدث صدفتا , كيف و لماذا ؟ شخصيا لا أدري !!
لقد بدأ الأمر بمحاولتي لتغيير شكل ال PopupMenu .. عندما لاحظت أن المقبض الذي حصلت عليه من الدالة GetMenu مختلف عن الذي حصلت عليه باستخدام Window Spy .
سرعان ما استنتجت أن الوينداوز يقوم بعمل نسخة عن المقبض الحقيقي , هذه النسخة لن تفيد في شيئ ان أردنا التعديل على مظهر المكون .
لوهلة اعتقدت أن الامر مستحيل , خصوصا عندما أيقنت أن مكون PopupActionBar مطور من الصفر !!
بورلاند قامت بتطوير مكون PopupActionBar من الصفر عوضا عن اشتقاقه من PopupMenu , و السبب يعود لتجاوز كل العقبات الخاصة ب PopupMenu .
فكرت في أن أعمل Clone لمكون PopupMenu واستبداله ب المكون PopupActionBar الذي يدعم ال VCL Style , لكن الصدفة تلعب دور كبير : صدفتا باطلاعي على سؤال احد السائلين الذي يريد أن يقوم بتطبيق هووك على رسائل النظام ..وجدت أنه يمكن الوصول للمقبض الحقيقي لل PopupMenu بتطبيق هووك على رسائل النظام ..
ثم كل ماحدث أني قمت بتغيير ال WndProc الخاص ب PopupMenu الى ال WndProc الخاص بي ..
استطعت الرسم على المكون من دون جعله OwnerDraw .. لكن الأمر لم ينتهي بعد : العديد و العديد من الغموض حول رسائل المكون , بحثت في النت ووجدت بعض الرسائل لكن بدون أي شروحات لماهية هذه الرسائل : قمت بعمل تحليل عميق لهذه الرسائل ثم قمت باعادة رسمه من الصفر ..
عند عمل الهووك استطعلت الولوج الى جميع ال PopupMenu الخاصة بالتطبيق (System Menu, Edit Popup Menu ,...) .
لكن المشكلة كانت مع TMenu & OwnerDraw : ان كان ال PopupMenu OwnerDraw لن تستطيع الحصول على Caption الخاصة ب ال Item . شكلت المشكلة تعقيدا كبيرا لي , الى غاية أن قمت بحلها بتطبيق هووك Hook على الدالة InsertMenuItem ..
عندما أنهيت العمل و حصلت على PopupMenu داعم لل VCL Style , توجهت أنظاري لدعم باقي المكونات ..
بنفس الطريقة : بعمل هووك على رسائل النظام و اقتناص الحدث Create للمكونات استطعت تغيير ال
WndProc ثم اعادة رسم المكون النستهدف ..
الآلية المستخدمة بسيطة :
-تنصيب هووك على رسائل النظام WH_CBT
- اقتناص الرسالة HCBT_CREATEWND التي تدل على أن مكون جديد تم انشائه .
- مقارنة كلاس المكون (Button , Edit , ...)
- تغيير ال WndProc الافتراضي الخاص بالمكون الى WndProc الخاص بي عن طريق الدالة SetWindowLongPtr
-اقتناص الرسائل المتعلقة بالرسم WM_PAINT , WM_PRINT , ..
-اعادة رسم المكون
-نداء ال WndProc الافتراضي (الأصلي).
الكلاسات المستخدمة في المشروع :
TControlWnd : الركيزة الأساسية لكل كلاس : جميع الكلاسات مشتقة من هذا الكلاس ماعدا الكلاس TPopupWnd & TThemedSysControls . الكلاس مسؤول عن تغيير ال WndProc و الحصول على بعض المعلومات حول المكون (العرض , الطول , المقبض , ...)
TEditWnd : مسؤول عن رسم مكون Edit .
TComboBoxWnd : مسؤول عن رسم مكون ComboBox .
TButtonWnd : مسؤول عن رسم Button , RadioButton , GroupeBox,CheckBox .
TPopupWnd : مسؤول عن رسم ال PopupMenu .
TDialogWnd : مسؤول عن رسم جميع النوافذ OpenDialog,ColorDialog,MessageBox , ...
TThemedSysControls : الكلاس المسؤول عن الهووك .
المكونات المدعومة :
- TMenu
- TPopupMenu
- System Menu
- TEdit PopupMenu
- MessageBox
- VCL Error Message
All Dialog :
- TFontDialog
- TColorDialog
- TSaveDialog
- TPrintDialog
- TReplaceDialog
- TFindDialog
- TTaskDialog
- TPageSetupDialog
- ......
- ......
لمن يريد المساهمة في المشروع : لاعادة رسم أي مكون يتوجب أن تقوم بالتوريث من الكلاس TControlWnd .
استخدام المكون TThemedSysControls :
لدعم مكونات النظام في برنامجك ستحتاج الى كتابة سطرين فقط :
PHP كود :
var
ThemedSysControls: TThemedSysControls;
procedure TMain.FormCreate(Sender: TObject);
begin
ThemedSysControls := TThemedSysControls.Create(Self);
end;
procedure TMain.FormDestroy(Sender: TObject);
begin
if Assigned(ThemedSysControls) then
ThemedSysControls.Free;
end;
![[صورة: 84TV7.png]](http://im42.gulfup.com/84TV7.png)
![[صورة: 35wG8.png]](http://im42.gulfup.com/35wG8.png)
![[صورة: 8LLoq.png]](http://im42.gulfup.com/8LLoq.png)
![[صورة: L9389.png]](http://im42.gulfup.com/L9389.png)
TODO :
Skin SpinButton
Skin ScroolBar
Support FireMonkey
Bugs :
لمن اطلع على السورس .. سيعلم أن المشروع طويل و معقد , لذلك بالتأكيد ستكون هناك أخطاء .
لم صادف أي أخطاء مع المكونات (لا أعلم ) , أرجــوا منه أن يذكر الخطأ في هذا الموضوع مع وصف دقيق وصورة ان أمكن .
لمن استطاع تحسين أي دالة من الدوال التي كتبتها فأرجــوا أن يتفضل بذكرها في هذا الموضوع .
لمن قام بدعم مكونات أخرى فأرجــوا أن يقوم بمراسلتي قبل أن يقوم بنشرها .
Download TThemedSysControls :
كود :
https://dl.dropboxusercontent.com/u/99625333/Delphi/ThemedSysControls%20V1.rar
Open Your Source .. Open Your Mind


![[صورة: aOTrT.png]](http://im41.gulfup.com/aOTrT.png)