فرض إعادة رسم من تماينمينو عند التعامل مع وم_نكبينت نفسك

StackOverflow https://stackoverflow.com//questions/24020728

سؤال

أنا مخصص اللوحة بلدي شريط التسمية التوضيحية في تطبيق كبير نوعا ما مع العديد من الأشكال وقررت أن تحاول أن تفعل ذلك بالطريقة القديمة من خلال التعامل مع بعض الرسائل نفسي ودونغ الرسم عندما أنا التعامل مع ونكباينت.

اللوحة نفسها تسير على ما يرام وتعمل بشكل أساسي.الشيء الوحيد الذي لن يعمل على الرغم من اللوحة تماينمينو.إما لدي معالج ويم نكاكتيفاتي الافتراضي رسم منطقة نونكلينت بأكملها (لا بد لي من تنفيذ رسالة ويم نكاكتيفاتي داخل معالج ويم نكاكتيفاتي) قبل اللوحة أكثر من ذلك ، والذي يسبب الخفقان التي على ما يبدو لا يمكن أن تكون ساعدت.أو يمكنني محاولة أن يكون المعالج الافتراضي من ونكباينت الطلاء فقط المستقيم التي تحتوي على تماينمينو ، مما يؤدي إلى نتيجة سلسة ، ولكن لا إعادة رسم القائمة.

سؤالي هو:

  • كيف يمكنني الحصول على تماينمينو وفقط تماينمينو طلاؤها عندما أنا التعامل مع وم_نكبينت نفسي?

لقد أعطيت الأمر بضع مرات وأعتقد أنني على الطريق الصحيح, لكني أصطدم بالحائط;ليس لدي ما يكفي من المعرفة حول ما أفعله ولا يمكنني العثور على وثائق واضحة حول هذا الموضوع.أهم جزء في الكود الخاص بي هو:

RedrawWindow(Handle, nil, MenuRegion, RDW_INVALIDATE or RDW_FRAME or RDW_NOERASE or RDW_ALLCHILDREN or RDW_UPDATENOW);

وأعتقد أنه بالضبط ما يحدث خطأ.(أو بالأحرى ، رمز حيث أحسب 'مينوريجيون'.ليس لدي أي فكرة عما إذا كان الأمر خاطئا لأنني أستخدم نظام إحداثيات خاطئ أو إذا كان ذلك لأنني أتعامل مع هذا بطريقة خاطئة تماما.

وهنا نسخة مخفضة من التعليمات البرمجية التي سيتم تجميع وتشغيل 'كما هو' في دلفي (ز 3):

unit Unit3;
interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus;
type
  TForm3 = class(TForm)
  private
    FDrawMenu: Boolean;
    function CalcFrameRegion: HRGN;
    function CalcMenuRegion: HRGN;
    procedure DrawMenu;
    procedure FormFrame(minimal: Boolean = false);
    procedure WMNCActivate(var message: TWMNCActivate); message WM_NCACTIVATE;
    procedure WMNCPaint(var message: TMessage); message WM_NCPAINT;
    procedure WMSIZE(var message : TWMSIZE); message WM_SIZE;
    constructor Create(AOwner: TComponent); override;
  public
    { Public declarations }
  end;
var
  Form3: TForm3;
implementation
{$R *.dfm}
{ TForm3 }
function TForm3.CalcFrameRegion: HRGN;
var
  YCaption, YFrame, XFrame: Integer;
begin
  YCaption := GetSystemMetrics(SM_CYCaption);
  YFrame := GetSystemMetrics(SM_CYFRAME);
  XFrame := GetSystemMetrics(SM_CXFRAME);
  Result :=  CreateRectRgn(0, 0, YCaption + YFrame, Width);
  Result := Result +  CreateRectRgn(0, 0, Height, XFrame);
  Result := Result + CreateRectRgn(0, Height - YFrame, Width, Height);
  Result := Result + CreateRectRgn(Width - XFrame, 0, Width, Height);
end;
function TForm3.CalcMenuRegion: HRGN;
var
  XFrame, YFrame, YCaption, YMenu: Integer;
begin
  XFrame := GetSystemMetrics(SM_CXFRAME);
  YFrame := GetSystemMetrics(SM_CYFRAME);
  YCaption := GetSystemMetrics(SM_CYCAPTION);
  YMenu := GetSystemMetrics(SM_CYMENU);
  Result := CreateRectRgn(XFrame, YFrame + YCaption, Width - XFrame, YFrame + YCaption + YMenu);
end;
constructor TForm3.Create(AOwner: TComponent);
var
  testItem: TMenuItem;
begin
  inherited;
  // Creating a MainMenu and attatching it to the form.
  Menu := TMainMenu.Create(self);
  // The menu need san item.
  testItem := TMenuItem.Create(Menu);
  testItem.Caption := 'test';
  Menu.Items.Add(testItem);
  FDrawMenu := false;
end;
procedure TForm3.FormFrame(minimal: Boolean);
var
  YCaption, YFrame, XFrame: Integer;
begin
  YCaption := GetSystemMetrics(SM_CYCaption);
  YFrame := GetSystemMetrics(SM_CYFRAME);
  XFrame := GetSystemMetrics(SM_CXFRAME);
  Canvas.Handle := GetWindowDC(Handle);
  Canvas.Pen.Style := psClear;
  Canvas.Brush.Style := bsSolid;
  Canvas.Brush.Color := clRed;
  if not minimal then begin
    Canvas.Rectangle(0, 0, Width + 1, YCaption + YFRame + 1);
    Canvas.Rectangle(0, YCaption + YFRame, XFrame + 1, Height + 1);
    Canvas.Rectangle(XFrame, Height - YFrame, Width + 1, Height + 1);
    Canvas.Rectangle(Width - XFrame, YCaption + YFRame, Width + 1, Height - YFrame + 1);
  end;
end;
procedure TForm3.DrawMenu;
var
  MenuRegion: HRGN;
begin
  if Assigned(Menu) then begin
    MenuRegion := CalcMenuRegion;
    FDrawMenu := true; // Make sure the inherited handler gets called.
    // Force a redraw of the region defined by MenuRegion.
    RedrawWindow(Handle, nil, MenuRegion,
                  RDW_INVALIDATE or RDW_FRAME or RDW_NOERASE or RDW_ALLCHILDREN or RDW_UPDATENOW);
    FDrawMenu := false; // Use the FormFrame function again.
  end;
end;
procedure TForm3.WMNCActivate(var message: TWMNCActivate);
begin
  FormFrame;
  message.Result := 1; // This makes sure the message gets handled properly.
end;
procedure TForm3.WMNCPaint(var message: TMessage);
begin
  if FDrawMenu then
    inherited // Gets called when the Menu has to be drawn.
  else
    FormFrame; // Gets called in all other cases.
end;
procedure TForm3.WMSIZE(var message: TWMSIZE);
begin
  inherited;
  DrawMenu;
end;
end.
هل كانت مفيدة؟

المحلول

"كيف يمكنني الحصول على تماينمينو وفقط تماينمينو طلاؤها عندما أنا التعامل مع وم_نكبينت نفسي?"

من الناحية النظرية يمكنك تعديل المنطقة WM_NCPAINT يتم تمريرها.حدد منطقة تتوافق مع منطقة شريط القوائم ، واترك الباقي.أدناه هو دليل على المفهوم:

procedure TForm3.WMNCPaint(var Message: TWMNCPaint);
var
  R: TRect;
  MenubarInfo: TMenuBarInfo;
  MenuRgn: HRGN;
begin
  FormFrame( whatever );

  MenubarInfo.cbSize := SizeOf(MenubarInfo);
  GetMenuBarInfo(Handle, OBJID_MENU, 0, MenubarInfo);

  MenuRgn := CreateRectRgnIndirect(MenubarInfo.rcBar);
  if Message.RGN <> 1 then
    DeleteObject(Message.RGN);
  Message.RGN := MenuRgn;

  inherited;
end;


في الممارسة العملية ، ستتخلى في النهاية عن هذا الطريق.لاحظ اختبار '1' في العينة أعلاه.لم يتم ذكر مقبض زائف لمنطقة التحديث في الوثائق.ومع ذلك ، فإن مقبض المنطقة هو دائما ' 1 ' لنافذة عادية.في الواقع ، لم يتم توثيق التعامل مع غير العميل بشكل صحيح.تخميني هو ، وذلك لأن نظام التشغيل نفسه لا يلعب وفقا للقواعد.خذ على سبيل المثال حقيقة أن منطقة نورث كارولاينا يتم رسمها أثناء التعامل الافتراضي مع WM_NCACTIVATE.ماذا التنشيط قد حصلت على أي علاقة مع نك اللوحة.لماذا يرسم نظام التشغيل وراء ظهرك?

اقتراحي هو ، واتخاذ الطريق الذي اتخذت أنماط فكل.ذات مرة كنت في رسم منطقة نورث كارولاينا ، رسم كل شيء.منطقة شريط القوائم هي جزء من منطقة غير العميل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top