ReactOS  0.4.12-dev-934-g9a4676f
CProgressDialog.cpp
Go to the documentation of this file.
1 /*
2  * Progress dialog
3  *
4  * Copyright 2007 Mikolaj Zalewski
5  * Copyright 2014 Huw Campbell
6  *
7  * this library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * this library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <precomp.h>
23 
24 #define COBJMACROS
25 
26 #define CANCEL_MSG_LINE 2
27 
28 /* Note: to avoid a deadlock we don't want to send messages to the dialog
29  * with the critical section held. Instead we only mark what fields should be
30  * updated and the dialog proc does the update */
31 #define UPDATE_PROGRESS 0x1
32 #define UPDATE_TITLE 0x2
33 #define UPDATE_LINE1 0x4
34 #define UPDATE_LINE2 (UPDATE_LINE1<<1)
35 #define UPDATE_LINE3 (UPDATE_LINE1<<2)
36 
37 
38 #define WM_DLG_UPDATE (WM_APP+1) /* set to the dialog when it should update */
39 #define WM_DLG_DESTROY (WM_APP+2) /* DestroyWindow must be called from the owning thread */
40 
41 #define ID_3SECONDS 101
42 
43 #define BUFFER_SIZE 256
44 
46 {
47  this->lines[0] = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, BUFFER_SIZE);
48  this->lines[1] = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, BUFFER_SIZE);
49  this->lines[2] = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, BUFFER_SIZE);
52 
53  this->lines[0][0] = this->lines[1][0] = this->lines[2][0] = UNICODE_NULL;
54  this->cancelMsg[0] = this->title[0] = UNICODE_NULL;
55 
56  this->clockHand = -1;
57  this->progressClock[29].ullMark = 0ull;
58  this->dwStartTime = GetTickCount();
59 
61 }
62 
64 {
65  if (this->hwnd)
66  this->end_dialog();
67  HeapFree(GetProcessHeap(), 0, this->lines[0]);
68  HeapFree(GetProcessHeap(), 0, this->lines[1]);
69  HeapFree(GetProcessHeap(), 0, this->lines[2]);
70  HeapFree(GetProcessHeap(), 0, this->cancelMsg);
71  HeapFree(GetProcessHeap(), 0, this->title);
72  DeleteCriticalSection(&this->cs);
73 }
74 
75 static void set_buffer(LPWSTR *buffer, LPCWSTR string)
76 {
77  if (!string)
78  {
79  (*buffer)[0] = UNICODE_NULL;
80  return;
81  }
82 
83  StringCbCopyW(*buffer, BUFFER_SIZE, string);
84 }
85 
87 {
91 };
92 
93 static void load_string(LPWSTR *buffer, HINSTANCE hInstance, UINT uiResourceId)
94 {
95  WCHAR string[256];
96 
97  LoadStringW(hInstance, uiResourceId, string, sizeof(string)/sizeof(string[0]));
98 
99  set_buffer(buffer, string);
100 }
101 
103 {
104  HWND hProgress = GetDlgItem(this->hwnd, IDC_PROGRESS_BAR);
105  SetWindowLongW(hProgress, GWL_STYLE,
106  GetWindowLongW(hProgress, GWL_STYLE)|PBS_MARQUEE);
107 }
108 
110 {
111  WCHAR empty[] = {0};
112 
113  if (dwUpdate & UPDATE_TITLE)
114  SetWindowTextW(this->hwnd, this->title);
115 
116  if (dwUpdate & UPDATE_LINE1)
117  SetDlgItemTextW(this->hwnd, IDC_TEXT_LINE, (this->isCancelled ? empty : this->lines[0]));
118  if (dwUpdate & UPDATE_LINE2)
119  SetDlgItemTextW(this->hwnd, IDC_TEXT_LINE+1, (this->isCancelled ? empty : this->lines[1]));
120  if (dwUpdate & UPDATE_LINE3)
121  SetDlgItemTextW(this->hwnd, IDC_TEXT_LINE+2, (this->isCancelled ? this->cancelMsg : this->lines[2]));
122 
124  {
125  ULONGLONG ullTotal = this->ullTotal;
127 
128  /* progress bar requires 32-bit coordinates */
129  while (ullTotal >> 32)
130  {
131  ullTotal >>= 1;
132  ullCompleted >>= 1;
133  }
134 
137  }
138 }
139 
141 {
142  SendMessageW(this->hwnd, WM_DLG_DESTROY, 0, 0);
143  /* native doesn't re-enable the window? */
144  if (this->hwndDisabledParent)
146  this->hwnd = NULL;
147 }
148 
150 {
152 
153  switch (msg)
154  {
155  case WM_INITDIALOG:
156  {
157  struct create_params *params = (struct create_params *)lParam;
158 
159  /* Note: until we set the hEvent, the object is protected by
160  * the critical section held by StartProgress */
162  This = params->This;
163  This->hwnd = hwnd;
164 
165  if (This->dwFlags & PROGDLG_NOPROGRESSBAR)
167  if (This->dwFlags & PROGDLG_NOCANCEL)
169  if (This->dwFlags & PROGDLG_MARQUEEPROGRESS)
170  This->set_progress_marquee();
171  if (This->dwFlags & PROGDLG_NOMINIMIZE)
173 
174  This->update_dialog(0xffffffff);
175  This->dwUpdate = 0;
176  This->isCancelled = FALSE;
177 
178  SetTimer(hwnd, ID_3SECONDS, 3 * 1000, NULL);
179 
180  SetEvent(params->hEvent);
181  return TRUE;
182  }
183 
184  case WM_DLG_UPDATE:
186  This->update_dialog(This->dwUpdate);
187  This->dwUpdate = 0;
189  return TRUE;
190 
191  case WM_DLG_DESTROY:
193  PostThreadMessageW(GetCurrentThreadId(), WM_NULL, 0, 0); /* wake up the GetMessage */
195 
196  return TRUE;
197 
198  case WM_CLOSE:
199  case WM_COMMAND:
200  if (msg == WM_CLOSE || wParam == IDCANCEL)
201  {
203  This->isCancelled = TRUE;
204 
205  if (!This->cancelMsg[0]) {
207  }
208 
209  This->set_progress_marquee();
211  This->update_dialog(UPDATE_LINE1|UPDATE_LINE2|UPDATE_LINE3);
213  }
214  return TRUE;
215 
216  case WM_TIMER:
218  if (This->progressClock[29].ullMark != 0ull) {
219  // We have enough info to take a guess
220  ULONGLONG sizeDiff = This->progressClock[This->clockHand].ullMark -
221  This->progressClock[(This->clockHand + 29) % 30].ullMark;
222  DWORD timeDiff = This->progressClock[This->clockHand].dwTime -
223  This->progressClock[(This->clockHand + 29) % 30].dwTime;
224  DWORD runDiff = This->progressClock[This->clockHand].dwTime -
225  This->dwStartTime;
226  ULONGLONG sizeLeft = This->ullTotal - This->progressClock[This->clockHand].ullMark;
227 
228  // A guess for time remaining based on the recent slope.
229  DWORD timeLeftD = (DWORD) timeDiff * ((double) sizeLeft) / ((double) sizeDiff);
230  // A guess for time remaining based on the start time and current position
231  DWORD timeLeftI = (DWORD) runDiff * ((double) sizeLeft) / ((double) This->progressClock[This->clockHand].ullMark);
232 
233  StrFromTimeIntervalW(This->lines[2], 128, timeLeftD * 0.3 + timeLeftI * 0.7 , 2);
234  This->update_dialog( UPDATE_LINE1 << 2 );
235  }
237 
238  return TRUE;
239  }
240  return FALSE;
241 }
242 
244 {
245  /* Note: until we set the hEvent in WM_INITDIALOG, the ProgressDialog object
246  * is protected by the critical section held by StartProgress */
247  struct create_params *params = (struct create_params *) lpParameter;
248  HWND hwnd;
249  MSG msg;
250 
253  params->hwndParent,
254  dialog_proc,
255  (LPARAM)params);
256 
257  while (GetMessageW(&msg, NULL, 0, 0) > 0)
258  {
259  if (!IsWindow(hwnd))
260  break;
261  if(!IsDialogMessageW(hwnd, &msg))
262  {
265  }
266  }
267 
268  return 0;
269 }
270 
272 {
273  static const INITCOMMONCONTROLSEX init = { sizeof(init), ICC_ANIMATE_CLASS };
274 
275  struct create_params params;
276  HANDLE hThread;
277 
278  // TRACE("(%p, %p, %x, %p)\n", this, punkEnableModeless, dwFlags, reserved);
279  if (punkEnableModeless || reserved)
280  FIXME("Reserved parameters not null (%p, %p)\n", punkEnableModeless, reserved);
282  FIXME("Flags PROGDLG_AUTOTIME not supported\n");
283  if (dwFlags & PROGDLG_NOTIME)
284  FIXME("Flags PROGDLG_NOTIME not supported\n");
285 
287 
288  EnterCriticalSection(&this->cs);
289 
290  if (this->hwnd)
291  {
292  LeaveCriticalSection(&this->cs);
293  return S_OK; /* as on XP */
294  }
295  this->dwFlags = dwFlags;
296  params.This = this;
297  params.hwndParent = hwndParent;
298  params.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
299 
302  CloseHandle(params.hEvent);
304 
305  this->hwndDisabledParent = NULL;
306  if (hwndParent && (dwFlags & PROGDLG_MODAL))
307  {
308  HWND hwndDisable = GetAncestor(hwndParent, GA_ROOT);
309  if (EnableWindow(hwndDisable, FALSE))
310  this->hwndDisabledParent = hwndDisable;
311  }
312 
313  LeaveCriticalSection(&this->cs);
314 
315  return S_OK;
316 }
317 
319 {
320  EnterCriticalSection(&this->cs);
321  if (this->hwnd)
322  this->end_dialog();
323  LeaveCriticalSection(&this->cs);
324 
325  return S_OK;
326 }
327 
329 {
330  HWND hwnd;
331 
332  EnterCriticalSection(&this->cs);
333  set_buffer(&this->title, pwzTitle);
334  this->dwUpdate |= UPDATE_TITLE;
335  hwnd = this->hwnd;
336  LeaveCriticalSection(&this->cs);
337 
338  if (hwnd)
340 
341  return S_OK;
342 }
343 
345 {
346  HWND hAnimation = GetDlgItem(this->hwnd, IDD_PROGRESS_DLG);
347  SetWindowLongW(hAnimation, GWL_STYLE,
349 
350  if(!Animate_OpenEx(hAnimation,hInstance,MAKEINTRESOURCEW(uiResourceId)))
351  return S_FALSE;
352 
353  return S_OK;
354 }
355 
357 {
358  return this->isCancelled;
359 }
360 
362 {
363  HWND hwnd;
364 
365  EnterCriticalSection(&this->cs);
366  this->ullTotal = ullTotal;
367  this->ullCompleted = ullCompleted;
368 
369  if (GetTickCount() - this->progressClock[(this->clockHand + 29) % 30].dwTime > 20) {
370  this->clockHand = (this->clockHand + 1) % 30;
372  this->progressClock[this->clockHand].dwTime = GetTickCount();
373  }
374 
375  this->dwUpdate |= UPDATE_PROGRESS;
376  hwnd = this->hwnd;
377  LeaveCriticalSection(&this->cs);
378 
379  if (hwnd)
381 
382  return S_OK; /* Windows sometimes returns S_FALSE */
383 }
384 
386 {
387  return this->SetProgress64(dwCompleted, dwTotal);
388 }
389 
391 {
392  HWND hwnd;
393 
394  if (reserved)
395  FIXME("reserved pointer not null (%p)\n", reserved);
396 
397  dwLineNum--;
398  if (dwLineNum >= 3) /* Windows seems to do something like that */
399  dwLineNum = 0;
400 
401  EnterCriticalSection(&this->cs);
402  set_buffer(&this->lines[dwLineNum], pwzLine);
403  this->dwUpdate |= UPDATE_LINE1 << dwLineNum;
404  hwnd = (this->isCancelled ? NULL : this->hwnd); /* no sense to send the message if window cancelled */
405  LeaveCriticalSection(&this->cs);
406 
407  if (hwnd)
409 
410  return S_OK;
411 }
412 
414 {
415  HWND hwnd;
416 
417  if (reserved)
418  FIXME("reserved pointer not null (%p)\n", reserved);
419 
420  EnterCriticalSection(&this->cs);
421  set_buffer(&this->cancelMsg, pwzMsg);
423  hwnd = (this->isCancelled ? this->hwnd : NULL); /* no sense to send the message if window not cancelled */
424  LeaveCriticalSection(&this->cs);
425 
426  if (hwnd)
428 
429  return S_OK;
430 }
431 
433 {
434  if (reserved)
435  FIXME("Reserved field not NULL but %p\n", reserved);
436 
437  return S_OK;
438 }
439 
441 {
442  EnterCriticalSection(&this->cs);
443  *phwnd = this->hwnd;
444  LeaveCriticalSection(&this->cs);
445  return S_OK;
446 }
447 
449 {
450  return E_NOTIMPL;
451 }
#define IDC_PROGRESS_BAR
Definition: resource.h:132
#define WM_NULL
Definition: winuser.h:1589
#define GA_ROOT
Definition: winuser.h:2743
#define BUFFER_SIZE
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
virtual HRESULT WINAPI SetAnimation(HINSTANCE hInstance, UINT uiResourceId)
virtual HRESULT WINAPI SetProgress64(ULONGLONG ullCompleted, ULONGLONG ullTotal)
HWND WINAPI GetAncestor(_In_ HWND, _In_ UINT)
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define PBM_SETRANGE32
Definition: commctrl.h:2160
CProgressDialog * This
#define IDD_PROGRESS_DLG
Definition: resource.h:134
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#define PBS_MARQUEE
Definition: commctrl.h:2170
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define SW_HIDE
Definition: winuser.h:762
static const WCHAR empty[]
Definition: main.c:49
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define CALLBACK
Definition: compat.h:27
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
#define ACS_AUTOPLAY
Definition: commctrl.h:4120
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:679
GLuint buffer
Definition: glext.h:5915
#define PBM_SETPOS
Definition: commctrl.h:2156
INT WINAPI StrFromTimeIntervalW(LPWSTR lpszStr, UINT cchMax, DWORD dwMS, int iDigits)
Definition: string.c:2139
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
UINT_PTR WPARAM
Definition: windef.h:207
#define ACS_CENTER
Definition: commctrl.h:4118
#define GetWindowLongPtrW
Definition: winuser.h:4698
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
int32_t INT_PTR
Definition: typedefs.h:62
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
BOOL WINAPI DestroyWindow(_In_ HWND)
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define DWORD
Definition: nt_native.h:44
static int init
Definition: wintirpc.c:33
WPARAM wParam
Definition: combotst.c:138
ULONGLONG ullTotal
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:597
#define IDC_TEXT_LINE
Definition: resource.h:133
BOOL WINAPI SetDlgItemTextW(_In_ HWND, _In_ int, _In_ LPCWSTR)
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HINSTANCE hInstance
Definition: charmap.c:20
virtual HRESULT WINAPI SetProgress(DWORD dwCompleted, DWORD dwTotal)
#define UNICODE_NULL
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
GLenum const GLfloat * params
Definition: glext.h:5645
unsigned int BOOL
Definition: ntddk_ex.h:94
LONG WINAPI SetWindowLongW(_In_ HWND, _In_ int, _In_ LONG)
#define FIXME(fmt,...)
Definition: debug.h:110
r reserved
Definition: btrfs.c:2655
#define S_FALSE
Definition: winerror.h:2357
static DWORD WINAPI dialog_thread(LPVOID lpParameter)
LONG WINAPI GetWindowLongW(_In_ HWND, _In_ int)
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:112
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
smooth NULL
Definition: ftsmooth.c:416
static HWND hwndParent
Definition: cryptui.c:300
virtual HRESULT WINAPI Timer(DWORD dwTimerAction, LPCVOID reserved)
virtual HRESULT WINAPI SetCancelMsg(LPCWSTR pwzMsg, LPCVOID reserved)
#define CANCEL_MSG_LINE
LONG_PTR LPARAM
Definition: windef.h:208
HINSTANCE GetResourceInstance()
Definition: atlcore.h:203
#define PROGDLG_NOMINIMIZE
Definition: shlobj.h:886
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:421
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
#define IDS_CANCELLING
Definition: resource.h:129
virtual HRESULT WINAPI StartProgressDialog(HWND hwndParent, IUnknown *punkEnableModeless, DWORD dwFlags, LPCVOID reserved)
DWORD dwTime
Definition: solitaire.cpp:25
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
LONG HRESULT
Definition: typedefs.h:77
uint64_t ULONGLONG
Definition: typedefs.h:65
static INT_PTR CALLBACK dialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
#define WM_TIMER
Definition: winuser.h:1718
#define WM_CLOSE
Definition: winuser.h:1603
#define WINAPI
Definition: msvc.h:8
CRITICAL_SECTION cs
#define UPDATE_PROGRESS
unsigned long DWORD
Definition: ntddk_ex.h:95
LRESULT WINAPI SendDlgItemMessageW(_In_ HWND, _In_ int, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define Animate_OpenEx(hwnd, hInst, szName)
Definition: commctrl.h:4137
#define PROGDLG_AUTOTIME
Definition: shlobj.h:884
#define UPDATE_TITLE
#define ICC_ANIMATE_CLASS
Definition: commctrl.h:65
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
progressMark progressClock[30]
BOOL WINAPI InitCommonControlsEx(const INITCOMMONCONTROLSEX *lpInitCtrls)
Definition: commctrl.c:893
virtual BOOL WINAPI HasUserCancelled()
#define DWLP_USER
Definition: winuser.h:866
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
LPVOID lpParameter
Definition: kernel32.h:234
#define UPDATE_LINE2
#define WM_COMMAND
Definition: winuser.h:1716
#define PROGDLG_MODAL
Definition: shlobj.h:883
#define WM_DLG_DESTROY
BOOL WINAPI EnableWindow(_In_ HWND, _In_ BOOL)
#define GWL_STYLE
Definition: winuser.h:846
#define S_OK
Definition: intsafe.h:59
virtual HRESULT WINAPI StopProgressDialog()
#define WS_MINIMIZEBOX
Definition: pedump.c:631
#define PROGDLG_MARQUEEPROGRESS
Definition: shlobj.h:888
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
void update_dialog(DWORD dwUpdate)
#define E_NOTIMPL
Definition: ddrawi.h:99
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define ACS_TRANSPARENT
Definition: commctrl.h:4119
unsigned int UINT
Definition: ndis.h:50
virtual HRESULT WINAPI SetLine(DWORD dwLineNum, LPCWSTR pwzLine, BOOL bPath, LPCVOID reserved)
#define UPDATE_LINE3
BOOL WINAPI GetMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
HANDLE hThread
Definition: wizard.c:27
static void load_string(LPWSTR *buffer, HINSTANCE hInstance, UINT uiResourceId)
#define msg(x)
Definition: auth_time.c:54
#define PROGDLG_NOTIME
Definition: shlobj.h:885
CONST void * LPCVOID
Definition: windef.h:191
virtual HRESULT WINAPI SetTitle(LPCWSTR pwzTitle)
HWND WINAPI CreateDialogParamW(_In_opt_ HINSTANCE, _In_ LPCWSTR, _In_opt_ HWND, _In_opt_ DLGPROC, _In_ LPARAM)
CAtlBaseModule _AtlBaseModule
Definition: atlbase.cpp:26
#define SetWindowLongPtrW
Definition: winuser.h:5215
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define UPDATE_LINE1
#define WM_DLG_UPDATE
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define IDCANCEL
Definition: winuser.h:825
ULONGLONG ullCompleted
#define INFINITE
Definition: serial.h:102
STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:166
#define PROGDLG_NOCANCEL
Definition: shlobj.h:889
static void set_buffer(LPWSTR *buffer, LPCWSTR string)
#define PROGDLG_NOPROGRESSBAR
Definition: shlobj.h:887
BOOL WINAPI PostThreadMessageW(_In_ DWORD, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_INITDIALOG
Definition: winuser.h:1715
LPARAM lParam
Definition: combotst.c:139
#define HeapFree(x, y, z)
Definition: compat.h:394
BOOL WINAPI IsDialogMessageW(_In_ HWND, _In_ LPMSG)
virtual HRESULT WINAPI GetWindow(HWND *phwnd)
virtual HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
#define ID_3SECONDS