将上下文菜单添加到 Inno Setup 页面
Adding context menu to Inno Setup page
如何向 Inno Setup 的特定页面添加一些上下文菜单?
例如在安装页面,如果用户在页面上右击,可以看到“取消”或“暂停”菜单项,可以进行一些操作。
Inno Setup 没有 API 上下文菜单,甚至没有处理鼠标点击的方法。因此,您需要实现自定义 Windows 消息处理程序并处理 WM_CONTEXTMENU
.
[Code]
const
GWL_WNDPROC = -4;
WM_CONTEXTMENU = [=10=]7B;
WM_COMMAND = 11;
type
WPARAM = UINT_PTR;
LPARAM = LongInt;
LRESULT = LongInt;
const
MF_BYPOSITION = 00;
MF_STRING = [=10=]00;
const
ID_MUTE = 0;
ID_STOP = 1;
function CallWindowProc(
lpPrevWndFunc: LongInt; hWnd: HWND; Msg: UINT; wParam: WPARAM;
lParam: LPARAM): LRESULT; external 'CallWindowProcW@user32.dll stdcall';
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: LongInt): LongInt;
external 'SetWindowLongW@user32.dll stdcall';
function CreatePopupMenu: THandle; external 'CreatePopupMenu@User32.dll stdcall';
function InsertMenu(
hMenu: THandle; uPosition: Cardinal; uFlags: Cardinal; uIDNewItem: Cardinal;
lpNewItem: string): Boolean;
external 'InsertMenuW@User32.dll stdcall';
function TrackPopupMenu(
hMenu: THandle; uFlags: Cardinal; x: Integer; y: Integer; nReserved: Integer;
hWnd: THandle; Rect: Integer): Boolean;
external 'TrackPopupMenu@User32.dll stdcall';
function ClientToScreen(hWnd: HWND; var lpPoint: TPoint): Boolean;
external 'ClientToScreen@user32.dll stdcall';
var
OldPageWndProc: LongInt;
Page: TWizardPage;
function GET_X_LPARAM(dw: DWORD): WORD; // aka LOWORD
begin
Result := WORD(dw);
end;
function GET_Y_LPARAM(dw: DWORD): WORD; // aka HIWORD
begin
Result := WORD((dw shr 16) and $FFFF);
end;
function PageWndProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
var
PopupMenu: THandle;
X, Y: Integer;
begin
if uMsg = WM_CONTEXTMENU then
begin
X := GET_X_LPARAM(lParam);
Y := GET_Y_LPARAM(lParam);
PopupMenu := CreatePopupMenu();
InsertMenu(PopupMenu, -1, MF_BYPOSITION or MF_STRING, ID_MUTE, 'Mute');
InsertMenu(PopupMenu, -1, MF_BYPOSITION or MF_STRING, ID_STOP, 'Stop');
TrackPopupMenu(PopupMenu, 0, X, Y, 0, Page.Surface.Handle, 0);
end
else
if uMsg = WM_COMMAND then
begin
if wParam = ID_MUTE then
begin
MsgBox('Muting', mbInformation, MB_OK);
Result := 0;
end
else
if wParam = ID_STOP then
begin
MsgBox('Stopping', mbInformation, MB_OK);
Result := 0;
end;
end
else
begin
Result := CallWindowProc(OldPageWndProc, hwnd, uMsg, wParam, lParam);
end;
end;
procedure InitializeWizard();
begin
Page := CreateCustomPage(wpWelcome, 'Page with context menu', '');
OldPageWndProc :=
SetWindowLong(Page.Surface.Handle, GWL_WNDPROC, CreateCallback(@PageWndProc));
end;
procedure DeinitializeSetup;
begin
SetWindowLong(Page.Surface.Handle, GWL_WNDPROC, OldPageWndProc);
end;
GWL_WNDPROC
代码基于Inno Setup - How to edit the "About Setup" dialog text box。
如果要添加图标,请参见 。
对于 CreateCallback
function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback
function from InnoTools InnoCallback 库。
如何向 Inno Setup 的特定页面添加一些上下文菜单?
例如在安装页面,如果用户在页面上右击,可以看到“取消”或“暂停”菜单项,可以进行一些操作。
Inno Setup 没有 API 上下文菜单,甚至没有处理鼠标点击的方法。因此,您需要实现自定义 Windows 消息处理程序并处理 WM_CONTEXTMENU
.
[Code]
const
GWL_WNDPROC = -4;
WM_CONTEXTMENU = [=10=]7B;
WM_COMMAND = 11;
type
WPARAM = UINT_PTR;
LPARAM = LongInt;
LRESULT = LongInt;
const
MF_BYPOSITION = 00;
MF_STRING = [=10=]00;
const
ID_MUTE = 0;
ID_STOP = 1;
function CallWindowProc(
lpPrevWndFunc: LongInt; hWnd: HWND; Msg: UINT; wParam: WPARAM;
lParam: LPARAM): LRESULT; external 'CallWindowProcW@user32.dll stdcall';
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: LongInt): LongInt;
external 'SetWindowLongW@user32.dll stdcall';
function CreatePopupMenu: THandle; external 'CreatePopupMenu@User32.dll stdcall';
function InsertMenu(
hMenu: THandle; uPosition: Cardinal; uFlags: Cardinal; uIDNewItem: Cardinal;
lpNewItem: string): Boolean;
external 'InsertMenuW@User32.dll stdcall';
function TrackPopupMenu(
hMenu: THandle; uFlags: Cardinal; x: Integer; y: Integer; nReserved: Integer;
hWnd: THandle; Rect: Integer): Boolean;
external 'TrackPopupMenu@User32.dll stdcall';
function ClientToScreen(hWnd: HWND; var lpPoint: TPoint): Boolean;
external 'ClientToScreen@user32.dll stdcall';
var
OldPageWndProc: LongInt;
Page: TWizardPage;
function GET_X_LPARAM(dw: DWORD): WORD; // aka LOWORD
begin
Result := WORD(dw);
end;
function GET_Y_LPARAM(dw: DWORD): WORD; // aka HIWORD
begin
Result := WORD((dw shr 16) and $FFFF);
end;
function PageWndProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
var
PopupMenu: THandle;
X, Y: Integer;
begin
if uMsg = WM_CONTEXTMENU then
begin
X := GET_X_LPARAM(lParam);
Y := GET_Y_LPARAM(lParam);
PopupMenu := CreatePopupMenu();
InsertMenu(PopupMenu, -1, MF_BYPOSITION or MF_STRING, ID_MUTE, 'Mute');
InsertMenu(PopupMenu, -1, MF_BYPOSITION or MF_STRING, ID_STOP, 'Stop');
TrackPopupMenu(PopupMenu, 0, X, Y, 0, Page.Surface.Handle, 0);
end
else
if uMsg = WM_COMMAND then
begin
if wParam = ID_MUTE then
begin
MsgBox('Muting', mbInformation, MB_OK);
Result := 0;
end
else
if wParam = ID_STOP then
begin
MsgBox('Stopping', mbInformation, MB_OK);
Result := 0;
end;
end
else
begin
Result := CallWindowProc(OldPageWndProc, hwnd, uMsg, wParam, lParam);
end;
end;
procedure InitializeWizard();
begin
Page := CreateCustomPage(wpWelcome, 'Page with context menu', '');
OldPageWndProc :=
SetWindowLong(Page.Surface.Handle, GWL_WNDPROC, CreateCallback(@PageWndProc));
end;
procedure DeinitializeSetup;
begin
SetWindowLong(Page.Surface.Handle, GWL_WNDPROC, OldPageWndProc);
end;
GWL_WNDPROC
代码基于Inno Setup - How to edit the "About Setup" dialog text box。
如果要添加图标,请参见
对于 CreateCallback
function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback
function from InnoTools InnoCallback 库。