mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-03 20:40:25 +02:00
win32: use TaskDialogIndirect for MessageDlg and ShowMessage on windows vista+
git-svn-id: trunk@28198 -
This commit is contained in:
parent
13f15fb3ff
commit
8e99ab359b
@ -72,6 +72,146 @@ type
|
||||
WINDOWINFO = tagWINDOWINFO;
|
||||
PWINDOWINFO = ^tagWINDOWINFO;
|
||||
|
||||
// ===================== Task Dialog =========================
|
||||
|
||||
PFTASKDIALOGCALLBACK = function(hwnd: HWND; msg: UINT; wParam: WPARAM; lParam: LPARAM; lpRefData: LONG_PTR): HRESULT; stdcall;
|
||||
|
||||
// _TASKDIALOG_FLAGS enum
|
||||
const
|
||||
TDF_ENABLE_HYPERLINKS = $0001;
|
||||
TDF_USE_HICON_MAIN = $0002;
|
||||
TDF_USE_HICON_FOOTER = $0004;
|
||||
TDF_ALLOW_DIALOG_CANCELLATION = $0008;
|
||||
TDF_USE_COMMAND_LINKS = $0010;
|
||||
TDF_USE_COMMAND_LINKS_NO_ICON = $0020;
|
||||
TDF_EXPAND_FOOTER_AREA = $0040;
|
||||
TDF_EXPANDED_BY_DEFAULT = $0080;
|
||||
TDF_VERIFICATION_FLAG_CHECKED = $0100;
|
||||
TDF_SHOW_PROGRESS_BAR = $0200;
|
||||
TDF_SHOW_MARQUEE_PROGRESS_BAR = $0400;
|
||||
TDF_CALLBACK_TIMER = $0800;
|
||||
TDF_POSITION_RELATIVE_TO_WINDOW = $1000;
|
||||
TDF_RTL_LAYOUT = $2000;
|
||||
TDF_NO_DEFAULT_RADIO_BUTTON = $4000;
|
||||
TDF_CAN_BE_MINIMIZED = $8000;
|
||||
|
||||
type
|
||||
TASKDIALOG_FLAGS = Integer; // Note: _TASKDIALOG_FLAGS is an int
|
||||
|
||||
// _TASKDIALOG_MESSAGES enum
|
||||
const
|
||||
TDM_NAVIGATE_PAGE = WM_USER+101;
|
||||
TDM_CLICK_BUTTON = WM_USER+102; // wParam = Button ID
|
||||
TDM_SET_MARQUEE_PROGRESS_BAR = WM_USER+103; // wParam = 0 (nonMarque) wParam != 0 (Marquee)
|
||||
TDM_SET_PROGRESS_BAR_STATE = WM_USER+104; // wParam = new progress state
|
||||
TDM_SET_PROGRESS_BAR_RANGE = WM_USER+105; // lParam = MAKELPARAM(nMinRange, nMaxRange)
|
||||
TDM_SET_PROGRESS_BAR_POS = WM_USER+106; // wParam = new position
|
||||
TDM_SET_PROGRESS_BAR_MARQUEE = WM_USER+107; // wParam = 0 (stop marquee), wParam != 0 (start marquee), lparam = speed (milliseconds between repaints)
|
||||
TDM_SET_ELEMENT_TEXT = WM_USER+108; // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR)
|
||||
TDM_CLICK_RADIO_BUTTON = WM_USER+110; // wParam = Radio Button ID
|
||||
TDM_ENABLE_BUTTON = WM_USER+111; // lParam = 0 (disable), lParam != 0 (enable), wParam = Button ID
|
||||
TDM_ENABLE_RADIO_BUTTON = WM_USER+112; // lParam = 0 (disable), lParam != 0 (enable), wParam = Radio Button ID
|
||||
TDM_CLICK_VERIFICATION = WM_USER+113; // wParam = 0 (unchecked), 1 (checked), lParam = 1 (set key focus)
|
||||
TDM_UPDATE_ELEMENT_TEXT = WM_USER+114; // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR)
|
||||
TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = WM_USER+115; // wParam = Button ID, lParam = 0 (elevation not required), lParam != 0 (elevation required)
|
||||
TDM_UPDATE_ICON = WM_USER+116; // wParam = icon element (TASKDIALOG_ICON_ELEMENTS), lParam = new icon (hIcon if TDF_USE_HICON_* was set, PCWSTR otherwise)
|
||||
|
||||
// _TASKDIALOG_NOTIFICATIONS enum
|
||||
const
|
||||
TDN_CREATED = 0;
|
||||
TDN_NAVIGATED = 1;
|
||||
TDN_BUTTON_CLICKED = 2; // wParam = Button ID
|
||||
TDN_HYPERLINK_CLICKED = 3; // lParam = (LPCWSTR)pszHREF
|
||||
TDN_TIMER = 4; // wParam = Milliseconds since dialog created or timer reset
|
||||
TDN_DESTROYED = 5;
|
||||
TDN_RADIO_BUTTON_CLICKED = 6; // wParam = Radio Button ID
|
||||
TDN_DIALOG_CONSTRUCTED = 7;
|
||||
TDN_VERIFICATION_CLICKED = 8; // wParam = 1 if checkbox checked, 0 if not, lParam is unused and always 0
|
||||
TDN_HELP = 9;
|
||||
TDN_EXPANDO_BUTTON_CLICKED = 10; // wParam = 0 (dialog is now collapsed), wParam != 0 (dialog is now expanded)
|
||||
|
||||
type
|
||||
_TASKDIALOG_BUTTON = packed record
|
||||
nButtonID: Integer;
|
||||
pszButtonText: PCWSTR;
|
||||
end;
|
||||
TASKDIALOG_BUTTON = _TASKDIALOG_BUTTON;
|
||||
TTASKDIALOG_BUTTON = TASKDIALOG_BUTTON;
|
||||
PTASKDIALOG_BUTTON = ^TASKDIALOG_BUTTON;
|
||||
|
||||
// _TASKDIALOG_ELEMENTS enum
|
||||
const
|
||||
TDE_CONTENT = 0;
|
||||
TDE_EXPANDED_INFORMATION = 1;
|
||||
TDE_FOOTER = 2;
|
||||
TDE_MAIN_INSTRUCTION = 3;
|
||||
|
||||
// _TASKDIALOG_ICON_ELEMENTS enum
|
||||
TDIE_ICON_MAIN = 0;
|
||||
TDIE_ICON_FOOTER = 1;
|
||||
|
||||
TD_WARNING_ICON = MAKEINTRESOURCEW(Word(-1));
|
||||
TD_ERROR_ICON = MAKEINTRESOURCEW(Word(-2));
|
||||
TD_INFORMATION_ICON = MAKEINTRESOURCEW(Word(-3));
|
||||
TD_SHIELD_ICON = MAKEINTRESOURCEW(Word(-4));
|
||||
TD_SHIELD_GRADIENT_ICON = MAKEINTRESOURCEW(Word(-5));
|
||||
TD_SHIELD_WARNING_ICON = MAKEINTRESOURCEW(Word(-6));
|
||||
TD_SHIELD_ERROR_ICON = MAKEINTRESOURCEW(Word(-7));
|
||||
TD_SHIELD_OK_ICON = MAKEINTRESOURCEW(Word(-8));
|
||||
TD_SHIELD_GRAY_ICON = MAKEINTRESOURCEW(Word(-9));
|
||||
|
||||
// _TASKDIALOG_COMMON_BUTTON_FLAGS enum
|
||||
TDCBF_OK_BUTTON = $0001; // selected control return value IDOK
|
||||
TDCBF_YES_BUTTON = $0002; // selected control return value IDYES
|
||||
TDCBF_NO_BUTTON = $0004; // selected control return value IDNO
|
||||
TDCBF_CANCEL_BUTTON = $0008; // selected control return value IDCANCEL
|
||||
TDCBF_RETRY_BUTTON = $0010; // selected control return value IDRETRY
|
||||
TDCBF_CLOSE_BUTTON = $0020; // selected control return value IDCLOSE
|
||||
|
||||
type
|
||||
TASKDIALOG_COMMON_BUTTON_FLAGS = Integer; // Note: _TASKDIALOG_COMMON_BUTTON_FLAGS is an int
|
||||
|
||||
_TASKDIALOGCONFIG = packed record
|
||||
cbSize: UINT;
|
||||
hwndParent: HWND;
|
||||
hInstance: HINST; // used for MAKEINTRESOURCE() strings
|
||||
dwFlags: TASKDIALOG_FLAGS; // TASKDIALOG_FLAGS (TDF_XXX) flags
|
||||
dwCommonButtons: TASKDIALOG_COMMON_BUTTON_FLAGS; // TASKDIALOG_COMMON_BUTTON (TDCBF_XXX) flags
|
||||
pszWindowTitle: PCWSTR; // string or MAKEINTRESOURCE()
|
||||
case PtrInt of
|
||||
0: (hMainIcon: HICON);
|
||||
1: (
|
||||
pszMainIcon: PCWSTR;
|
||||
pszMainInstruction: PCWSTR;
|
||||
pszContent: PCWSTR;
|
||||
cButtons: UINT;
|
||||
pButtons: PTASKDIALOG_BUTTON;
|
||||
nDefaultButton: Integer;
|
||||
cRadioButtons: UINT;
|
||||
pRadioButtons: PTASKDIALOG_BUTTON;
|
||||
nDefaultRadioButton: Integer;
|
||||
pszVerificationText: PCWSTR;
|
||||
pszExpandedInformation: PCWSTR;
|
||||
pszExpandedControlText: PCWSTR;
|
||||
pszCollapsedControlText: PCWSTR;
|
||||
case PtrInt of
|
||||
0: (hFooterIcon: HICON);
|
||||
1: (
|
||||
pszFooterIcon: PCWSTR;
|
||||
pszFooter: PCWSTR;
|
||||
pfCallback: PFTASKDIALOGCALLBACK;
|
||||
lpCallbackData: LONG_PTR;
|
||||
cxWidth: UINT; // width of the Task Dialog's client area in DLU's. If 0, Task Dialog will calculate the ideal width.
|
||||
);
|
||||
);
|
||||
end;
|
||||
TASKDIALOGCONFIG = _TASKDIALOGCONFIG;
|
||||
PTASKDIALOGCONFIG = ^TASKDIALOGCONFIG;
|
||||
TTASKDIALOGCONFIG = TASKDIALOGCONFIG;
|
||||
|
||||
// ==================== End TaskDialog =======================
|
||||
|
||||
|
||||
// AlphaBlend is only defined for win98&2k and up
|
||||
// load dynamic and use ownfunction if not defined
|
||||
var
|
||||
@ -85,6 +225,9 @@ var
|
||||
UpdateLayeredWindow: function(hWnd: HWND; hdcDst: HDC; pptDst: PPoint; psize: PSize;
|
||||
hdcSrc: HDC; pptSrc: PPoint; crKey: COLORREF; pblend: PBlendFunction; dwFlags: DWORD): BOOL; stdcall;
|
||||
IsProcessDPIAware: function: BOOL; stdcall;
|
||||
TaskDialogIndirect: function(const pTaskConfig: PTASKDIALOGCONFIG; pnButton: PInteger; pnRadioButton: PInteger; pfVerificationFlagChecked: PBOOL): HRESULT; stdcall;
|
||||
TaskDialog: function(hwndParent: HWND; hInstance: HINST; pszWindowTitle: PCWSTR; pszMainInstruction: PCWSTR; pszContent: PCWSTR;
|
||||
dwCommonButtons: TASKDIALOG_COMMON_BUTTON_FLAGS; pszIcon: PCWSTR; pnButton: PInteger): HRESULT; stdcall;
|
||||
|
||||
const
|
||||
// ComCtlVersions
|
||||
@ -567,17 +710,30 @@ begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function _TaskDialogIndirect(const pTaskConfig: PTASKDIALOGCONFIG; pnButton: PInteger; pnRadioButton: PInteger; pfVerificationFlagChecked: PBOOL): HRESULT; stdcall;
|
||||
begin
|
||||
Result := E_NOTIMPL;
|
||||
end;
|
||||
|
||||
function _TaskDialog(hwndParent: HWND; hInstance: HINST; pszWindowTitle: PCWSTR; pszMainInstruction: PCWSTR; pszContent: PCWSTR;
|
||||
dwCommonButtons: TASKDIALOG_COMMON_BUTTON_FLAGS; pszIcon: PCWSTR; pnButton: PInteger): HRESULT; stdcall;
|
||||
begin
|
||||
Result := E_NOTIMPL;
|
||||
end;
|
||||
|
||||
const
|
||||
msimg32lib = 'msimg32.dll';
|
||||
user32lib = 'user32.dll';
|
||||
shell32lib = 'shell32.dll';
|
||||
gdi32lib = 'gdi32.dll';
|
||||
comctl32lib = 'comctl32.dll';
|
||||
|
||||
var
|
||||
msimg32handle: THandle = 0;
|
||||
user32handle: THandle = 0;
|
||||
shell32handle: THandle = 0;
|
||||
gdi32handle: THandle = 0;
|
||||
comctl32handle: THandle = 0;
|
||||
|
||||
procedure Initialize;
|
||||
var
|
||||
@ -671,6 +827,21 @@ begin
|
||||
then Pointer(SetLayout) := p;
|
||||
end;
|
||||
|
||||
// Defaults
|
||||
Pointer(TaskDialogIndirect) := @_TaskDialogIndirect;
|
||||
Pointer(TaskDialog) := @_TaskDialog;
|
||||
|
||||
comctl32handle := LoadLibrary(comctl32lib);
|
||||
if comctl32handle <> 0 then
|
||||
begin
|
||||
p := GetProcAddress(comctl32handle, 'TaskDialogIndirect');
|
||||
if p <> nil
|
||||
then Pointer(TaskDialogIndirect) := p;
|
||||
|
||||
p := GetProcAddress(comctl32handle, 'TaskDialog');
|
||||
if p <> nil
|
||||
then Pointer(TaskDialog) := p;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure Finalize;
|
||||
@ -694,6 +865,10 @@ begin
|
||||
if gdi32handle <> 0 then
|
||||
FreeLibrary(gdi32handle);
|
||||
gdi32handle := 0;
|
||||
|
||||
if comctl32handle <> 0 then
|
||||
FreeLibrary(comctl32handle);
|
||||
comctl32handle := 0;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
@ -35,7 +35,7 @@ interface
|
||||
}
|
||||
uses
|
||||
Windows, ActiveX, Classes, Translations, ComCtrls, Controls, Buttons,
|
||||
ExtCtrls, Forms, GraphMath, GraphType, InterfaceBase, LCLIntf,
|
||||
ExtCtrls, Forms, Dialogs, GraphMath, GraphType, InterfaceBase, LCLIntf,
|
||||
LCLType, LMessages, StdCtrls, SysUtils, Win32Def, Graphics, Menus, CommCtrl,
|
||||
MultiMon, Themes{, Win32Debug};
|
||||
|
||||
@ -249,6 +249,7 @@ uses
|
||||
Win32WSMenus,
|
||||
Win32WSSpin,
|
||||
Win32WSStdCtrls,
|
||||
Win32WSDialogs,
|
||||
Win32Themes,
|
||||
////////////////////////////////////////////////////
|
||||
Win32Extra, LclProc, LCLMessageGlue;
|
||||
|
@ -590,6 +590,86 @@ begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TWin32WidgetSet.PromptUser(const DialogCaption, DialogMessage: String;
|
||||
DialogType: longint; Buttons: PLongint; ButtonCount, DefaultIndex,
|
||||
EscapeResult: Longint): Longint;
|
||||
var
|
||||
i: Integer;
|
||||
Caption: String;
|
||||
TaskConfig: TTASKDIALOGCONFIG;
|
||||
DialogButtons: PTASKDIALOG_BUTTON;
|
||||
State: TApplicationState;
|
||||
begin
|
||||
if (WindowsVersion >= wvVista) and ThemeServices.ThemesEnabled then
|
||||
begin
|
||||
FillChar(TaskConfig, SizeOf(TaskConfig), 0);
|
||||
TaskConfig.cbSize := SizeOf(TaskConfig);
|
||||
// if we skip hwndParent our form will be a root window - with the taskbar item and icon
|
||||
// this is unwanted
|
||||
if Assigned(Screen.ActiveCustomForm) then
|
||||
TaskConfig.hwndParent := Screen.ActiveCustomForm.Handle
|
||||
else
|
||||
if Assigned(Application.MainForm) then
|
||||
TaskConfig.hwndParent := Application.MainForm.Handle
|
||||
else
|
||||
TaskConfig.hwndParent := AppHandle;
|
||||
TaskConfig.hInstance := HInstance;
|
||||
TaskConfig.dwFlags := TDF_ALLOW_DIALOG_CANCELLATION;
|
||||
if DialogCaption <> '' then
|
||||
Caption := DialogCaption
|
||||
else
|
||||
case DialogType of
|
||||
idDialogConfirm,
|
||||
idDialogInfo,
|
||||
idDialogWarning,
|
||||
idDialogError: Caption := GetDialogCaption(DialogType);
|
||||
else
|
||||
Caption := Application.Title;
|
||||
end;
|
||||
TaskConfig.pszWindowTitle := PWideChar(UTF8ToUTF16(Caption));
|
||||
|
||||
case DialogType of
|
||||
idDialogConfirm:
|
||||
begin
|
||||
TaskConfig.hMainIcon := LoadIcon(0, IDI_QUESTION);
|
||||
TaskConfig.dwFlags := TaskConfig.dwFlags or TDF_USE_HICON_MAIN;
|
||||
end;
|
||||
idDialogInfo: TaskConfig.pszMainIcon := TD_INFORMATION_ICON;
|
||||
idDialogWarning: TaskConfig.pszMainIcon := TD_WARNING_ICON;
|
||||
idDialogError: TaskConfig.pszMainIcon := TD_ERROR_ICON;
|
||||
idDialogShield: TaskConfig.pszMainIcon := TD_SHIELD_ICON;
|
||||
else
|
||||
TaskConfig.dwFlags := TaskConfig.dwFlags or TDF_USE_HICON_MAIN;
|
||||
end;
|
||||
|
||||
TaskConfig.pszMainInstruction := PWideChar(UTF8ToUTF16(DialogMessage));
|
||||
|
||||
TaskConfig.cButtons := ButtonCount;
|
||||
GetMem(DialogButtons, SizeOf(TTASKDIALOG_BUTTON) * ButtonCount);
|
||||
for i := 0 to ButtonCount - 1 do
|
||||
begin
|
||||
DialogButtons[i].nButtonID := Buttons[i];
|
||||
DialogButtons[i].pszButtonText := UTF8StringToPWideChar(GetButtonCaption(Buttons[i]));
|
||||
end;
|
||||
TaskConfig.pButtons := DialogButtons;
|
||||
TaskConfig.nDefaultButton := DefaultIndex;
|
||||
|
||||
State := SaveApplicationState;
|
||||
try
|
||||
if TaskDialogIndirect(@TaskConfig, @Result, nil, nil) <> S_OK then
|
||||
Result := EscapeResult;
|
||||
finally
|
||||
RestoreApplicationState(State);
|
||||
for i := 0 to ButtonCount - 1 do
|
||||
FreeMem(DialogButtons[i].pszButtonText);
|
||||
FreeMem(DialogButtons);
|
||||
end;
|
||||
end
|
||||
else
|
||||
Result := inherited PromptUser(DialogCaption, DialogMessage, DialogType,
|
||||
Buttons, ButtonCount, DefaultIndex, EscapeResult);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: RawImage_CreateBitmaps
|
||||
Params: ARawImage:
|
||||
|
@ -57,6 +57,8 @@ function GetDesignerDC(WindowHandle: HWND): HDC; override;
|
||||
function IntfSendsUTF8KeyPress: boolean; override;
|
||||
function IsDesignerDC(WindowHandle: HWND; DC: HDC): Boolean; override;
|
||||
|
||||
function PromptUser(const DialogCaption, DialogMessage : String; DialogType : longint; Buttons : PLongint; ButtonCount, DefaultIndex, EscapeResult : Longint) : Longint; override;
|
||||
|
||||
function RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask: HBitmap; ASkipMask: Boolean = False): Boolean; override;
|
||||
function RawImage_DescriptionFromBitmap(ABitmap: HBITMAP; out ADesc: TRawImageDescription): Boolean; override;
|
||||
function RawImage_DescriptionFromDevice(ADC: HDC; out ADesc: TRawImageDescription): Boolean; override;
|
||||
|
@ -254,13 +254,13 @@ begin
|
||||
if UnicodeEnabledOS then
|
||||
PreferredSizeStatusBar := CreateWindowExW(0, STATUSCLASSNAMEW,
|
||||
nil, Flags,
|
||||
0, 0, 0, 0, Parent, 0, HInstance, Nil)
|
||||
0, 0, 0, 0, Parent, 0, HInstance, nil)
|
||||
else
|
||||
PreferredSizeStatusBar := CreateWindowEx(0, STATUSCLASSNAME, nil,
|
||||
Flags, 0, 0, 0, 0, Parent,0 , HInstance, Nil);
|
||||
Flags, 0, 0, 0, 0, Parent,0 , HInstance, nil);
|
||||
{$else}
|
||||
PreferredSizeStatusBar := CreateWindowEx(0, STATUSCLASSNAME, nil,
|
||||
Flags, 0, 0, 0, 0, Parent, 0, HInstance, Nil);
|
||||
Flags, 0, 0, 0, 0, Parent, 0, HInstance, nil);
|
||||
{$endif}
|
||||
GetWindowRect(PreferredSizeStatusBar, R);
|
||||
PreferredStatusBarHeight := R.Bottom - R.Top;
|
||||
@ -464,7 +464,7 @@ end;
|
||||
class procedure TWin32WSStatusBar.GetPreferredSize(const AWinControl: TWinControl;
|
||||
var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean);
|
||||
begin
|
||||
if (PreferredStatusBarHeight=0) then
|
||||
if (PreferredStatusBarHeight = 0) then
|
||||
InitializePreferredStatusBarHeight;
|
||||
|
||||
PreferredHeight := PreferredStatusBarHeight;
|
||||
|
@ -122,6 +122,8 @@ function OpenFileDialogCallBack(Wnd: HWND; uMsg: UINT; wParam: WPARAM;
|
||||
|
||||
function SaveApplicationState: TApplicationState;
|
||||
procedure RestoreApplicationState(AState: TApplicationState);
|
||||
function UTF8StringToPWideChar(const s: string) : PWideChar;
|
||||
function UTF8StringToPAnsiChar(const s: string) : PAnsiChar;
|
||||
|
||||
implementation
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user