فرض إعادة رسم من تماينمينو عند التعامل مع وم_نكبينت نفسك
-
21-12-2019 - |
سؤال
أنا مخصص اللوحة بلدي شريط التسمية التوضيحية في تطبيق كبير نوعا ما مع العديد من الأشكال وقررت أن تحاول أن تفعل ذلك بالطريقة القديمة من خلال التعامل مع بعض الرسائل نفسي ودونغ الرسم عندما أنا التعامل مع ونكباينت.
اللوحة نفسها تسير على ما يرام وتعمل بشكل أساسي.الشيء الوحيد الذي لن يعمل على الرغم من اللوحة تماينمينو.إما لدي معالج ويم نكاكتيفاتي الافتراضي رسم منطقة نونكلينت بأكملها (لا بد لي من تنفيذ رسالة ويم نكاكتيفاتي داخل معالج ويم نكاكتيفاتي) قبل اللوحة أكثر من ذلك ، والذي يسبب الخفقان التي على ما يبدو لا يمكن أن تكون ساعدت.أو يمكنني محاولة أن يكون المعالج الافتراضي من ونكباينت الطلاء فقط المستقيم التي تحتوي على تماينمينو ، مما يؤدي إلى نتيجة سلسة ، ولكن لا إعادة رسم القائمة.
سؤالي هو:
- كيف يمكنني الحصول على تماينمينو وفقط تماينمينو طلاؤها عندما أنا التعامل مع وم_نكبينت نفسي?
لقد أعطيت الأمر بضع مرات وأعتقد أنني على الطريق الصحيح, لكني أصطدم بالحائط;ليس لدي ما يكفي من المعرفة حول ما أفعله ولا يمكنني العثور على وثائق واضحة حول هذا الموضوع.أهم جزء في الكود الخاص بي هو:
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
.ماذا التنشيط قد حصلت على أي علاقة مع نك اللوحة.لماذا يرسم نظام التشغيل وراء ظهرك?
اقتراحي هو ، واتخاذ الطريق الذي اتخذت أنماط فكل.ذات مرة كنت في رسم منطقة نورث كارولاينا ، رسم كل شيء.منطقة شريط القوائم هي جزء من منطقة غير العميل.