خرید بک لینک

منوها - یک نگاه نسبتا ساده

شروع موضوع توسط knowhow ‏5 دسامبر 2003 در انجمن منابع آموزشی

  1. knowhow

    knowhow مدیران قدیمی

    تاریخ عضویت:
    ‏25 دسامبر 2002
    نوشته ها:
    3,477
    تشکر شده:
    20
    littlerabbit

    abolfazlerfani wrote:

    در مورد منو بايد بگويم که آنها در حالت عادي يکي از انعطاف پذيرترين ابزار برنامه نويسي هستند اما اگر نخواهيم وارد مباحث پيشرفته شويم راهي براي تغيير دادن فونت منوهايي که با پرچم MF_STRING (منوهاي عادي- مثل منوهاي وي بي يا منوهاي ويژوال سي) مشخص شده اند وجود ندارد.
    تنها راه ساده موجود اين است که فونت تمام منوهاي سيستم را عوض کنيم - از طريق Display Properties \Appearance يا از طريف دستکاvي مستقيم در رجيستري (HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics\MenuFont البته اين مقدار به صورت باينري است نه رشته اي- حالا مشکلي پيش ميايد و آن مساله عوض شدن فونت در کل سيستم است -اين براي امثال من که ترجيح ميدهم همه چيز توسط خودم انتخاب شود کمي ناخوشايند است که يک برنامه تنظيمات سيستم مرا به هم بريزد-

    راه ديگري هم هست که متاسفانه بدون ترس از Crash در برنامه هاي ويژوال بيسيک نميتوان از آن استفاده کرد
    توابع API منو تنها دو تابع دارند که ميتواند اطلاعات مربوط به يک منو و آيتم هاي آن را بگيرد اما هيچکدام راهي براي تغيير فونت ارايه نداده اند.(همه توابع ديگر نيز توسط اين دو تابع قابل جايگزيني هستند منتها با کمي دردسر بيشتر ) يکي GetMenuInfo و يکي GetMenuItemInfo .

    شايد براي شما هم مساله اين است که برنامه هايي مثل IncrediMail يا Axialis IconWorkshop (که دومي حتي سيستم منوي آن هم دستکاري شده ) چه طور اينکار را ميکنند؟
    آنها همه منوهاي خود را با فلگ MF_OWNERDRAW مشخص ميکنند و در هنگام اجراي برنامه به پيغام هاي WM_MEASUREITEM و WM_DRAWITEM جواب ميدهند که اين کار در وي بي امکان ندارد ( در يک تاپيک دوستي ادعا کرده بود که اين کار - پردازش پيغامهاي Custome در وي بي بدون Hook يا SubClass ممکن است اما هيچوقت اين راه را نشان نداد- متاسفانه- ) به هر حال اگر کسي هست که اين مطلب را ميحواند و ميتواند اين کار را بکند (بدون Hook و SubClass ) آنوقت به من هم ياد بدهد (البته بهتر است وقت خودتان را تلف نکنيد!)
    حالا ميرويم سراغ دلفي منو و فونت اگر ديده باشيد دلفي ميتواند فونت ها را براي منو عوض کند اين به معناي نقض گفته هاي بالايي نيست. منو هاي دلفي استاندارد نيستند (گر چه دقيقا با منو هاي استاندارد مشابه هستند) حتي خصيصه Handle که در Help دلفي ادعا شده براي استفاده در توابع Api مفيد است به درد اين کار نميخورد مثلا نميتوان توسط توابع AppendMenu يا InsertMenuItem گزينه اي به اين منو ها اضافه کرد.

    و اما مشکل اين دوست. اگر تمام کنترل هاي ديگر مثل Command و يا Label درست نمايش داده ميشوند يعني اينکه فونت مربوط به منوها در برنامه شما نميتواند علائم گچپژ را نشان دهد اما فونت مربوط به کنترل ها ميتواند. (ميتوانيد براي رفع اين مشکل از Display Properties \Appearance فونت منوها را عوض کنيد. (احتمالا فونت کنترل ها MS SansSerif است و فونت مربوط به منو ها Tahoma ) اگر مشکلتان حل نشود من متاسفانه راه ديگري بلد نيستم.

    درمورد مساله دوم. ميتوانيد يک تابع ساده (با يک Switch ساده) که کل کد هاي معادل دار را به کد معادلشان تبديل کند را بنويسيد و شايد من مشکل شما را درست متوجه نشده ام؟؟


    براي درک بيشتر مساله منو هاي Owner Draw يک مثال با دلفي نوشتم که از چند تا Api ساده استفاده ميکند. چون ميخواستم که توابع مربوط به Device Context يا DC را اضافه نکنم از Canvas دلفي استفاده کردم.

    تابع اول
    کد:
    function GetSystemMenu(hWnd: HWND; bRevert: BOOL): HMENU; stdcall; 
    function GetSystemMenu; external 'user32.dll' name 'GetSystemMenu'; 
    
    اين تابع منوي سيتم يک پنجره را برميگرداند (منوي کنترل هم گفته ميشود) آرگومان اول دستگيره پنجره است و آرگومان دوم اگر True باشد منو به حالت اول برميگردد و اگر False باشد يک کپي از منو به عنوان بازگشتي در اختيار شماست.

    کد:
    function AppendMenu(hMenu: HMENU; uFlags, uIDNewItem: UINT;  lpNewItem: PChar): BOOL; stdcall; 
    function AppendMenu; external 'user32.dll' name 'AppendMenuA'; 
    
    اين يکي هم يک گزينه به انتهاي منو اضافه ميکند. hMenu دستگيره منو است (که مثلا با تابع GetSystemMenu ميتواند گرفته شود) آرگومان دوم خصيصه منو را مشخص ميکند (ميتوانيد MSDN را براي همه گزينه ها ببينيد) آرگومان بعدي مشخصه منو که منو با آن شناسايي ميشود و آرگومان سوم متني که در منو نمايش داده ميشود (اگر منو با پرچم MF_STRING ساخته شود)
    دو پيغام استاندارد هم استفاده شده يکي WM_MEASUREITEM و يکي WM_DRAWITEM که اولي براي تنظيم مشخصات اوليه مثل اندازه و دومي براي رسم آيتم استفاده ميشود براي توضيحات بيشتر به MSDN مراجعه کنيد .

    اينهم کد فرم به صورت کامل. البته مثال فقط طريقه را نشان ميدهد و مطمئنا کار خاصي انجام نميدهد.(اين مثال آيکون برنامه را در سيستم منو به عنوان يک آيتم اضافه ميکند و رويداد آن را مديريت ميکند. FOldAppMessage هم متغيري است که فقط محض احتياط اضافه شده.تا اگر در زنجيره پردازش پيغام تابع ديگري هم هست سرش بي کلاه نماند)
    کد:
    unit Unit1; 
    
    interface 
    
    uses 
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
      Dialogs; 
    
    type 
      TForm1 = class(TForm) 
        procedure FormCreate(Sender: TObject); 
      private 
        { Private declarations } 
        DelphiCanvas : TCanvas; 
        FOldAppMessage : TMessageEvent; 
    
        procedure OnWM_MEASUREITEM(var Msg : TMessage);message WM_MEASUREITEM; 
        procedure OnWM_DRAWITEM(var Msg : TMessage);message WM_DRAWITEM; 
        procedure OnAppMessage (var Msg: TMsg; var Handled: Boolean); 
      public 
        { Public declarations } 
      end; 
    
    var 
      Form1: TForm1; 
    const 
        SC_NEWITEM = 200; 
    implementation 
    
    {$R *.dfm} 
    
    procedure TForm1.FormCreate(Sender: TObject); 
    var 
        SysMnu : HMENU; 
    begin 
        SysMnu:=GetSystemMenu(Handle,False); 
        AppendMenu(SysMnu,MF_SEPARATOR,SC_NEWITEM+1,nil); 
        AppendMenu(SysMnu,MF_OWNERDRAW ,SC_NEWITEM,nil); 
    
        FOldAppMessage:=Application.OnMessage; 
        Application.OnMessage:=OnAppMessage; 
    
        DelphiCanvas:=TCanvas.Create; 
    end; 
    
    procedure TForm1.OnWM_MEASUREITEM(var Msg : TMessage); 
    var 
        MeItem : PMeasureItemStruct; 
    begin 
        inherited; 
        if Msg.WParam<>0 then 
            Exit; 
        MeItem:=Pointer(Msg.LParam); 
        if MeItem^.itemID<>SC_NEWITEM then 
            Exit; 
        MeItem^.itemHeight:=Application.Icon.Height; 
    end; 
    
    procedure TForm1.OnWM_DRAWITEM(var Msg : TMessage); 
    var 
        MePaint : PDrawItemStruct; 
        Rect : TRect; 
    begin 
        inherited; 
        if Msg.WParam<>0 then 
            Exit; 
        MePaint:=Pointer(Msg.LParam); 
        if MePaint^.itemID<>SC_NEWITEM then 
            Exit; 
        DelphiCanvas.Handle:=MePaint^.hDC; 
    
        Rect:=MePaint^.rcItem; 
        if (MePaint^.itemState and ODS_SELECTED)<>0  then 
        begin 
            DelphiCanvas.Brush.Color:=clMaroon ; 
            DelphiCanvas.FillRect(Rect); 
            DelphiCanvas.Draw(Rect.Left-(Application.Icon.Width div 2)+(Rect.Right-Rect.Left) div 2 , 
                                Rect.Top,Application.Icon); 
        end 
        else 
        begin 
            DelphiCanvas.Brush.Color:=clMenu ; 
            DelphiCanvas.FillRect(Rect); 
            DelphiCanvas.Draw(Rect.Left-(Application.Icon.Width div 2)+(Rect.Right-Rect.Left) div 2 , 
                                Rect.Top,Application.Icon); 
        end; 
    
    end; 
    
    procedure TForm1.OnAppMessage(var Msg: TMsg; var Handled: Boolean); 
    begin 
    
        Handled:=False; 
        if Msg.message=WM_SYSCOMMAND then 
        begin 
        if (Msg.wParam and $FFFFFFFF ) =SC_NEWITEM then 
                ShowMessage('You click on my delphi icon. what you want?'); 
        end; 
    
        if Assigned(FOldAppMessage) then 
            FOldAppMessage(Msg,Handled); 
    
    end; 
    
    end. 
    
    

    حالا اگر بخواهيد از يک فونت خاص استفاده کنيد يا حتي اگر بخواهيد به صورت نقاشي عمل کنيد کار سختي نيست. يعني مشکل فارسي به راحتي حل ميشود (البته در دلفي و به طرز مشابهي سي ).


    موفق باشيد
    خرگوش کوچولو
    ( ;<
     
  2. بازدیدیار - افزایش بازدید سایت و سیگنال های برندخرید بک لینک
  3. littlerabbit

    littlerabbit مدیر بازنشسته کاربر فعال

    تاریخ عضویت:
    ‏13 جولای 2003
    نوشته ها:
    667
    تشکر شده:
    5
    محل سکونت:
    Iran
    اينو تازه ديدم! گرچه مربوط به خيلي وقت پيشه. فكر ميردم تو جريان هك كذايي از بين رفته. اما هنوز سر جاشه! اما با يه نويسنده جديد :lol: خوب منم ميارمش تو بخش دلفي.
     
عسل طبیعی و گرده گل ایرانیخرید و فروش اتوماتیک ارزهای الکترونیکی