2016-06-07 15 views
1

我正在與Windows 10中的德爾福XE7。我有一個TMainMenuBar在主窗體和模態輔助窗體上。問題是如果輔助表單還包含TMemo,輔助表單上的加速鍵不會激活菜單。例如,如果輔助表單具有文件菜單,則Alt + F不會打開文件菜單。但是,如果alt被按下並釋放,「文件」將突出顯示,「F」帶下劃線並按下F將打開菜單。請注意,如果TMemo被移除,問題就會消失。此外,主窗體上的Tmemo不會導致主窗體上的菜單出現問題。德爾福TActionMainMenu加速器的中學形式

我已經在「輔助表單上的TActionMainMenuBar加速鍵」上進行了搜索,但沒有一個點擊描述了這個特殊問題,儘管討論了該組件和加速鍵的其他問題。有沒有人知道如何在兩個表單上使用TActionMainMenuBar的同時獲得所需的行爲? (由於各種原因,我更喜歡不使用標準的TMenu。)

+0

你確定它是否與備忘錄存在?我敢打賭,這取決於備忘錄是否有重點。 –

+0

@JerryDodge你是對的,問題不是TMemo本身,而是存在一個可以關注的控件。例如,我可以刪除TMemo並使用表單上的組合框或radiogroup獲得相同的結果。如果備忘錄,組合框或radiogroup被禁用,問題就會消失。 – TomT

回答

5

這是一個VCL設計問題。 (下面的解釋可能有些偏差,我用XE2跟蹤,行爲並不完全相同,您可能需要在解決方案部分留下一個消息處理程序。)

菜單欄加速器生成WM_SYSCOMMAND信息。你確切的加速器情形作爲一個例子,API documentation

如果wParam爲SC_KEYMENU,lParam中包含用於與ALT鍵,顯示彈出菜單 鍵的字符代碼。對於 示例,按ALT + F顯示文件彈出窗口將導致一個 WM_SYSCOMMAND與wParam等於SC_KEYMENU和lParam等於'f'。

動作菜單欄是專有的VCL組件。由於這種窗體的默認窗口過程沒有機會處理它們的加速器消息。組件本身有代碼來模擬行爲(TCustomActionMainMenuBar.WMSysCommand),但它必須傳遞消息才能做到這一點。 VCL的設計問題是,只有主窗體上的動作菜單欄纔有機會。

A TWinControl收到WM_SYSCOMMAND(輔助表單本身或本例中的備註),使其父表單(輔助表單)執行CM_APPSYSCOMMAND。收到該消息後,表單(同樣是輔助表單)將消息發送到應用程序窗口。 CM_APPSYSCOMMAND應用程序的處理程序,再次將消息轉換爲WM_SYSCOMMAND並將其發送到主窗體。

我只能猜測,但這個設計背後的目的可以是,能夠從沒有菜單欄的輔助窗體訪問主菜單。

在任何情況下,在切換到本機菜單的情況下,您必須在消息由VCL處理之前截取並轉發消息到輔助表單上的操作菜單欄。可以有其他方法來實現這一點,但我試過並似乎工作是這樣的:

type 
    TSecondaryForm = class(TForm) 
    ... 
    protected 
    procedure CMAppsyscommand(var Message: TMessage); message CM_APPSYSCOMMAND; 
    procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND; 
    ... 


procedure TSecondaryForm.CMAppsyscommand(var Message: TMessage); 
begin 
    if ActionMainMenuBar1.Perform(PMessage(Message.LParam).Msg,, 
     PMessage(Message.LParam).WParam, PMessage(Message.LParam).LParam) = 0 then 
    inherited; 
end; 

// you may not need the below handler 
procedure TSecondaryForm.WMSysCommand(var Message: TWMSysCommand); 
begin 
    if ActionMainMenuBar1.Perform(Message.Msg, 
     TMessage(Message).WParam, TMessage(Message).LParam) = 0 then 
    inherited; 
end;