這是一個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;
你確定它是否與備忘錄存在?我敢打賭,這取決於備忘錄是否有重點。 –
@JerryDodge你是對的,問題不是TMemo本身,而是存在一個可以關注的控件。例如,我可以刪除TMemo並使用表單上的組合框或radiogroup獲得相同的結果。如果備忘錄,組合框或radiogroup被禁用,問題就會消失。 – TomT