عرض تلميح تلميح الأدوات على عنصر قائمة معطل لقائمة منبثقة

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

سؤال

لذلك لديّ tmenuitem متصل بتوزيع على tpopupmenu للحصول على tdbgrid (في الواقع الطرف الثالث ، لكنك تحصل على الفكرة). استنادًا إلى الصف المحدد في الشبكة ، يتم تمكين التوتر أو تعطيله. ما أريده هو أن أكون قادرًا على عرض تلميح للمستخدم يشرح سبب تعطيل العنصر.

بقدر ما أريد تلميحًا على عنصر قائمة معاق ، دعنا نقول فقط إنني بالاتفاق مع جويل.

تحتوي جميع Tmenuitem على خاصية تلميح ، ولكن أفضل ما يمكنني قوله أنه يتم استخدامه فقط معالج الأحداث tapplication.onhint لإلقاء التلميح في tstatusbar أو بعض المعالجة الخاصة الأخرى. أنا وجدت مقالا حول كيفية إنشاء نافذة خاصة بك ل tmenuitems من tmainmenu ، ولكنها لا تعمل على tmenuitem من tpopupmenu. إنه يعمل من خلال التعامل مع رسالة WM_MENUSElect ، والتي لا أستطيع أن أقول بقدر ما لا يتم إرسالها على tpopupmenu.

هل كانت مفيدة؟

المحلول

تتم معالجة WM_MenusElect بالفعل لعناصر القائمة في قوائم المنبثقة أيضًا ، ولكن ليس بواسطة Windows Proc للنموذج الذي يحتوي على قائمة (منبثقة) ، ولكن بواسطة نافذة مساعد غير مرئية تم إنشاؤها بواسطة Menus.popuplist. لحسن الحظ ، يمكنك (على الأقل تحت Delphi 5) الوصول إلى هذا HWND عبر القوائم. popuplist.window.

يمكنك الآن استخدام الطريقة القديمة لنافذ الفئة الفرعية ، كما هو موضح على سبيل المثال في هذا مقالة Codegear, ، للتعامل مع WM_MENUSElect أيضا لقوائم المنبثقة. سيكون HWND صالحًا بعد إنشاء TPOPUPMENU الأول قبل تدمير كائن TPOPUPMENU الأخير.

يجب أن يكشف اختبار سريع مع التطبيق التجريبي في المقالة المرتبطة في السؤال ما إذا كان هذا سيعمل.

يحرر: إنه يعمل بالفعل. لقد تغيرت المثال المرتبط لإظهار تلميحات أيضا لقائمة المنبثقة. فيما يلي الخطوات:

أضف معالجًا لـ OnDestroy ، وهو متغير عضو في النافذة القديمة Proc وطريقة لنافذ النموذج الجديد إلى النموذج:

TForm1 = class(TForm)
  ...
  procedure FormCreate(Sender: TObject);
  procedure FormDestroy(Sender: TObject);
  procedure ApplicationEvents1Hint(Sender: TObject);
private
  miHint : TMenuItemHint;
  fOldWndProc: TFarProc;
  procedure WMMenuSelect(var Msg: TWMMenuSelect); message WM_MENUSELECT;
  procedure PopupListWndProc(var AMsg: TMessage);
end;

قم بتغيير معالج oncreate للنموذج لتصنيف نافذة popuplist الخفية ، وتنفيذ الاستعادة المناسبة لنافذة Proc في معالج ondestroy:

procedure TForm1.FormCreate(Sender: TObject);
var
  NewWndProc: TFarProc;
begin
  miHint := TMenuItemHint.Create(self);

  NewWndProc := MakeObjectInstance(PopupListWndProc);
  fOldWndProc := TFarProc(SetWindowLong(Menus.PopupList.Window, GWL_WNDPROC,
    integer(NewWndProc)));
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  NewWndProc: TFarProc;
begin
  NewWndProc := TFarProc(SetWindowLong(Menus.PopupList.Window, GWL_WNDPROC,
    integer(fOldWndProc)));
  FreeObjectInstance(NewWndProc);
end;

تنفيذ النافذة الفرعية Proc:

procedure TForm1.PopupListWndProc(var AMsg: TMessage);

  function FindItemForCommand(APopupMenu: TPopupMenu;
    const AMenuMsg: TWMMenuSelect): TMenuItem;
  var
    SubMenu: HMENU;
  begin
    Assert(APopupMenu <> nil);
    // menuitem
    Result := APopupMenu.FindItem(AMenuMsg.IDItem, fkCommand);
    if Result = nil then begin
      // submenu
      SubMenu := GetSubMenu(AMenuMsg.Menu, AMenuMsg.IDItem);
      if SubMenu <> 0 then
        Result := APopupMenu.FindItem(SubMenu, fkHandle);
    end;
  end;

var
  Msg: TWMMenuSelect;
  menuItem: TMenuItem;
  MenuIndex: integer;
begin
  AMsg.Result := CallWindowProc(fOldWndProc, Menus.PopupList.Window,
    AMsg.Msg, AMsg.WParam, AMsg.LParam);
  if AMsg.Msg = WM_MENUSELECT then begin
    menuItem := nil;
    Msg := TWMMenuSelect(AMsg);
    if (Msg.MenuFlag <> $FFFF) or (Msg.IDItem <> 0) then begin
      for MenuIndex := 0 to PopupList.Count - 1 do begin
        menuItem := FindItemForCommand(PopupList.Items[MenuIndex], Msg);
        if menuItem <> nil then
          break;
      end;
    end;
    miHint.DoActivateHint(menuItem);
  end;
end;

يتم ذلك لجميع القوائم المنبثقة في حلقة ، حتى يتم العثور على أول عنصر مطابق أو قائمة فرعية.

نصائح أخرى

لست متأكدًا مما إذا كان ذلك مفيدًا ، لكنني قمت بإنشاء نافذة تلميح متعددة الخطوط الخاصة بي (لـ Delphi7) لتتمكن من إظهار المزيد ثم سطر واحد من النص. إنه مفتوح المصدر ويمكنك العثور عليه هنا.

هناك بعض الأعمال التي ينطوي عليها عرضه على الموقع الصحيح على الشاشة ، ولكن لديك تحكم كامل عليها.

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