uLib  User mode C/C++ extended API library for Win32 programmers.
UserUtil.cpp
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode library.
3 // Module: User32 utility functions (Migrated from UtilFunc.cpp)
4 // Author: Copyright (c) Love Nystrom
5 // License: NNOSL (BSD descendant, see NNOSL.txt in the base directory).
6 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 
8 #include <uLib/Common.h>
9 #include <uLib/UtilFunc.h>
10 #include <uLib/Debug.h>
11 #include <uLib/StrFunc.h>
12 
13 //*****************************************************************************
14 // User32 functions
15 //*****************************************************************************
16 
17 UINT DispatchMessagesFor( HWND hWnd )
18 {
19  MSG msg;
20  UINT nMsg = 0;
21  while( PeekMessage( &msg, hWnd, 0,0, PM_REMOVE ))
22  {
23  TranslateMessage( &msg );
24  DispatchMessage( &msg );
25  nMsg++;
26  }
27  return nMsg;
28 }
29 
30 #if 0 // UM wrapper for user32!EndTask
31 bool EndTask( HWND hAppWnd, BOOL ShutDown, BOOL Force )
32 {
33  static BOOL (WINAPI *_EndTask)( HWND hWnd, BOOL ShutDown, BOOL Force );
34  if (!_EndTask)
35  {
36  HMODULE hMod = GetModuleHandle( _T("User32.dll") );
37  if (hMod) (FARPROC&)_EndTask = GetProcAddress( hMod, _T("EndTask") );
38  }
39  return (_EndTask ? bool_cast(_EndTask( hAppWnd, ShutDown, Force )) : false);
40 }
41 #endif
42 
43 
44 //-----------------------------------------------------------------------------
45 // Clipboard
46 //-----------------------------------------------------------------------------
47 
48 bool OpenEmptyClipboard( HWND hWnd )
49 {
50  BOOL ok = OpenClipboard( hWnd );
51  if (ok) EmptyClipboard();
52  return bool_cast( ok );
53 }
54 
55 UINT EnumerateClipFormats( HWND hCBOwner, PFClipFmtAction Action, PVOID UserData )
56 {
57  UINT nFmtsEnum = 0;
58  // NOTE: EnumClipboardFormats fails if clipboard is opened with a NULL owner.
59  if (OpenClipboard( hCBOwner ))
60  {
61  UINT nFmtsAvail = CountClipboardFormats();
62  for( UINT ix = 0, clipFmt = 0; ix < nFmtsAvail; ++ix )
63  {
64  clipFmt = EnumClipboardFormats( clipFmt );
65  if (!clipFmt) break; else nFmtsEnum++;
66  if (Action && !Action( clipFmt, UserData )) break;
67  }
68  CloseClipboard();
69  }
70  return nFmtsEnum;
71 }
72 
73 bool PutClipHandle( HWND hCBOwner, HANDLE hClip, UINT clipFmt )
74 {
75  BOOL ok = OpenEmptyClipboard( hCBOwner );
76  if ( ok )
77  {
78  hClip = SetClipboardData( clipFmt, hClip );
79  CloseClipboard();
80  ok = (hClip != NULL);
81  }
82  return bool_cast( ok );
83 }
84 
85 HANDLE GetClipHandle( UINT clipFmt )
86 {
87  HANDLE hClip = NULL;
88  if (OpenClipboard( NULL ))
89  {
90  hClip = GetClipboardData( clipFmt ); // Clipboard still owns it!
91  // NB: Empirical tests show the clip handle is *still valid* after CloseClipboard.
92  // Presumably at least for a moment long enough to copy it...
93  CloseClipboard();
94  }
95  return hClip;
96 }
97 
98 static bool putClipStr( HWND hCBOwner, PVOID pDup, WORD Fmt )
99 {
100  bool ok = (pDup != NULL);
101  if ( ok )
102  {
103  HANDLE hDup = GlobalHandle( pDup );
104  ok = ((GlobalUnlock( hDup ) == 0) && (GetLastError() == 0));
105  if (ok) ok = PutClipHandle( hCBOwner, hDup, Fmt );
106  if (!ok) GlobalFree( hDup ); // If Unlock or PutClip failed, free the duplicate.
107  }
108  return ok;
109 }
110 
111 bool PutClipboardStringA( HWND hCBOwner, ACSTR Text )
112 {
113  ASTR pDup = GlobalDupStrA( Text );
114  return putClipStr( hCBOwner, pDup, CF_TEXT );
115 }
116 
117 bool PutClipboardStringW( HWND hCBOwner, WCSTR Text )
118 {
119  WSTR pDup = GlobalDupStrW( Text );
120  return putClipStr( hCBOwner, pDup, CF_UNICODETEXT );
121 }
122 
124 {
125  #ifdef _UNICODE
126  static const UINT Fmt = CF_UNICODETEXT;
127  #else
128  static const UINT Fmt = CF_TEXT;
129  #endif
130  HANDLE hClip = GetClipHandle( Fmt );
131  CSTR pzClip = hClip ? (CSTR) GlobalLock( hClip ) : NULL;
132 
133  CSTR pzDup = pzClip ? GlobalDupStr( pzClip ) : NULL;
134 
135  if (pzClip) GlobalUnlock( hClip );
136  return pzDup;
137 }
138 
139 PVOID DupClipboardData( UINT clipFmt, PUINT pSize )
140 {
141  PVOID pDup = NULL;
142  if (OpenClipboard( NULL ))
143  {
144  HANDLE hClip = GetClipboardData( clipFmt );
145  UINT clipSize = hClip ? (UINT) GlobalSize( hClip ) : 0; // size may be > than usage
146  PVOID pClip = clipSize ? GlobalLock( hClip ) : NULL;
147 
148  pDup = pClip ? GlobalAllocPtr( GHND, clipSize ) : NULL;
149  if (pDup) memcpy( pDup, pClip, clipSize ); // might be inefficient (if size >> usage)
150  if (pSize) *pSize = clipSize;
151 
152  if (pClip) GlobalUnlock( hClip );
153  CloseClipboard();
154  }
155  return pDup;
156 }
157 
158 //-----------------------------------------------------------------------------
159 // Window cbWndExtra/cbClassExtra floating point data
160 //-----------------------------------------------------------------------------
161 
163 
164 typedef union __fp32u {
165  long i;
166  float f;
167  } _fp32u;
168 
169 typedef union __fp64u {
170  long i[2];
172  double d;
173  } _fp64u;
174 
176 
177 void SetWindowFloat( HWND hCtl, int Index, float Value )
178 {
179  _fp32u fp;
180  fp.f = Value;
181  SetWindowLong( hCtl, Index, fp.i );
182 }
183 
184 float GetWindowFloat( HWND hCtl, int Index )
185 {
186  _fp32u fp;
187  fp.i = GetWindowLong( hCtl, Index );
188  return fp.f;
189 }
190 
191 void SetWindowDouble( HWND hCtl, int Index, double Value )
192 {
193  _fp64u fp;
194  fp.d = Value;
195  #ifdef _WIN64
196  SetWindowLongPtr( hCtl, Index, fp.i64 );
197  #else
198  SetWindowLong( hCtl, Index, fp.i[0] );
199  SetWindowLong( hCtl, Index+4, fp.i[1] );
200  #endif
201 }
202 
203 double GetWindowDouble( HWND hCtl, int Index )
204 {
205  _fp64u fp;
206  #ifdef _WIN64
207  fp.i64 = GetWindowLongPtr( hCtl, Index );
208  #else
209  fp.i[0] = GetWindowLong( hCtl, Index );
210  fp.i[1] = GetWindowLong( hCtl, Index+4 );
211  #endif
212  return fp.d;
213 }
214 
215 void SetClassFloat( HWND hCtl, int Index, float Value )
216 {
217  _fp32u fp;
218  fp.f = Value;
219  SetClassLong( hCtl, Index, fp.i );
220 }
221 
222 float GetClassFloat( HWND hCtl, int Index )
223 {
224  _fp32u fp;
225  fp.i = GetClassLong( hCtl, Index );
226  return fp.f;
227 }
228 
229 void SetClassDouble( HWND hCtl, int Index, double Value )
230 {
231  _fp64u fp;
232  fp.d = Value;
233  #ifdef _WIN64
234  SetClassLongPtr( hCtl, Index, fp.i64 );
235  #else
236  SetClassLong( hCtl, Index, fp.i[0] );
237  SetClassLong( hCtl, Index+4, fp.i[1] );
238  #endif
239 }
240 
241 double GetClassDouble( HWND hCtl, int Index )
242 {
243  _fp64u fp;
244  #ifdef _WIN64
245  fp.i64 = GetClassLongPtr( hCtl, Index );
246  #else
247  fp.i[0] = GetClassLong( hCtl, Index );
248  fp.i[1] = GetClassLong( hCtl, Index+4 );
249  #endif
250  return fp.d;
251 }
252 
253 //-----------------------------------------------------------------------------
254 // MsgBox
255 //-----------------------------------------------------------------------------
256 
257 #define _MAX_DBGMSG_ 512 /* Equal to kernel debugger message buffer size */
258 
259 static CSTR mbox_Caption( CSTR Caption, HWND Owner )
260 {
261  static TCHAR title[128];
262  if (!Caption)
263  {
264  Caption = title; title[0] = 0;
265  // If owner != NULL, use it's window title, else no title.
266  if (Owner) GetWindowText( Owner, title, dimof(title) );
267  }
268  return Caption;
269 }
270 
271 int __cdecl MsgBox( HWND owner, UINT type, CSTR cap, CSTR msg, ... )
272 {
273  TCHAR buf[_MAX_DBGMSG_];
274  va_list va;
275 
276  va_start( va, msg );
277  _vstprintf_s( buf, dimof(buf), msg, va );
278  va_end( va );
279 
280  cap = mbox_Caption( cap, owner );
281  return MessageBox( owner, buf, cap, type );
282 }
283 
284 bool __cdecl SetCaption( HWND hwnd, CSTR fmt, ... )
285 {
286  TCHAR sbuf[256];
287  va_list va;
288 
289  va_start( va, fmt );
290  _vstprintf_s( sbuf, dimof(sbuf), fmt, va );
291  va_end( va );
292  return bool_cast( SetWindowText( hwnd, sbuf ));
293 }
294 
295 //-----------------------------------------------------------------------------
296 // AsyncMsgBox[Ex] --> Self threaded message boxes..
297 //-----------------------------------------------------------------------------
298 
300 
301 #define MB_SYSICONMASK 0x00000070L
302 #ifndef MB_ICONMASK
303  #define MB_ICONMASK 0x000000F0L
304  #define MB_USERICON 0x00000080L
305 #endif
306 
307 struct MsgBoxParams : MSGBOXPARAMS // AsyncMsgBox[Ex] control data block..
308 {
309  // UINT cbSize;
310  // HWND hwndOwner;
311  // HINSTANCE hInstance;
312  // LPCTSTR lpszText;
313  // LPCTSTR lpszCaption;
314  // DWORD dwStyle;
315  // LPCTSTR lpszIcon;
316  // DWORD_PTR dwContextHelpId;
317  // MSGBOXCALLBACK lpfnMsgBoxCallback;
318  // DWORD dwLanguageId;
319 
320  PINT_PTR pResult; // Pointer to MessageBox result reciever.
321  HWND hBox; // MessageBox window handle.
322 
323  MsgBoxParams( CSTR title, WORD maxText, UINT flags );
324  ~MsgBoxParams();
325 };
327 
328 MsgBoxParams::MsgBoxParams( CSTR sTitle, WORD maxText, UINT uFlags )
329 {
330  cbSize = sizeof(MSGBOXPARAMS);
331  lpszText = newStrBuf( maxText );
332  lpszCaption = newStr( sTitle );
333  pResult = NULL;
334  hBox = NULL;
335 
336  dwStyle = uFlags;
337  hwndOwner = ::hMainWnd; // Default
338  hInstance = ::hInstance; // Default
339  dwContextHelpId = 0;
340  lpfnMsgBoxCallback = NULL;
341  dwLanguageId = MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ); // == 0,
342  lpszIcon = (dwStyle & MB_USERICON) ? IDI_WINLOGO : NULL; // Default icon.
343  TRACE_IF( dwStyle & MB_USERICON, DP_DEBUG, _F("lpszIcon=%p\n"), lpszIcon );
344 }
345 
347 {
348  deleteStr( lpszText );
349  deleteStr( lpszCaption );
350 }
351 
353 
354 // Enable programmatic close of the MessageBox..
355 // Use a WH_CALLWNDPROC hook to get the MessageBox window handle.
356 // Use TLS to transfer the control data ptr from __MBThread to __MBHook.
357 // Return the MessageBox handle so we can to abort it on command.
358 
359 static HHOOK _hMBCwpHook = NULL;
360 static DWORD _MBTlsIndex = 0;
361 
362 static WINHOOKPROC __MBCwpHook( int Code, WPARAM wp, LPARAM lp )
363 // This hook retrieves the MessageBox window handle and transfers
364 // the control data ptr to the message box window data.
365 {
366  LRESULT rc = CallNextHookEx( _hMBCwpHook, Code, wp, lp );
367  PCWPSTRUCT cwp = (PCWPSTRUCT) lp;
368  if ( cwp )
369  {
370  CHAR clsName[80];
371  // Detect the MessageBox window creation..
372  if (cwp->hwnd && GetClassNameA( cwp->hwnd, clsName, dimof(clsName) )
373  && (strncmp( clsName, "#32770", 6 ) == 0) // WC_DIALOG (i.e. the message box)
374  && (cwp->message == WM_CREATE))
375  {
376  PMsgBoxParams _mbp = (PMsgBoxParams) TlsGetValue( _MBTlsIndex );
377  SetWindowLongPtr( cwp->hwnd, DWLP_USER, (LPARAM)_mbp );
378 
379  _mbp->hBox = cwp->hwnd; // The MessageBox window handle.
380 
381  TRACE( DP_DEBUG, _F("MessageBox (%s) handle = 0x%p\n"), _mbp->lpszCaption, _mbp->hBox );
382  // We don't need the hook any further, so unhook to prevent a bunch
383  // of internal Win32 exceptions when the message box closes...
384  // And we don't need the TLS slot either, so free it.
385 
386  if (_hMBCwpHook) {
387  UnhookWindowsHookEx( _hMBCwpHook ); _hMBCwpHook = NULL;
388  }
389  if (_MBTlsIndex) {
390  TlsFree( _MBTlsIndex ); _MBTlsIndex = 0;
391  }
392  }
393  }
394  return rc;
395 }
396 
397 static THREADPROC __MBThread( PVOID pData )
398 // This thread invokes the MessageBox so it doesn't block the calling thread.
399 {
400  PMsgBoxParams _mbp = (PMsgBoxParams) pData;
401  //TRACE( DP_DEBUG, _F("ENTER: %s\n"), _mbp->lpszText );
402  if (_mbp->hwndOwner)
403  {
404  if ( !(_mbp->dwStyle & (MB_SYSTEMMODAL | MB_TASKMODAL)) )
405  // Sacrifice MB_APPLMODAL WM_HELP to facilitate non-blocking box.
406  _mbp->hwndOwner = NULL; // Un-block...
407  }
408 
409  DWORD thrId = GetCurrentThreadId();
410  while( _hMBCwpHook ) SleepEx( 10,true ); // Serialize the hook...
411  _hMBCwpHook = SetWindowsHookEx( WH_CALLWNDPROC, __MBCwpHook, hInstance, thrId );
412 
413  // Use TLS to transfer the _mbp pointer to __MBCwpHook..
414 
415  if (!_MBTlsIndex) _MBTlsIndex = TlsAlloc();
416  TlsSetValue( _MBTlsIndex, _mbp );
417 
418  // Invoke the (modal) messge box, which in turns invokes
419  // our hook that retrieves the message box window handle.
420 
421  TRACE( DP_DEBUG, _F("Invoking MessageBoxIndirect (%s)\n"), _mbp->lpszCaption );
422  DWORD ret = MessageBoxIndirect( _mbp ); // Spin internal system message loop.
423  TRACE( DP_DEBUG, _F("MessageBoxIndirect (%s) returned %lu\n"), _mbp->lpszCaption, ret );
424 
425  if (_mbp->pResult) *_mbp->pResult = ret; // Return the result.
426  delete _mbp; // Deallocate the control data.
427  return ret; // Ref. GetExitCodeThread..
428 }
429 
430 HANDLE __cdecl AsyncMsgBox( UINT Flags, PINT_PTR pResult, CSTR Title, CSTR Fmt, ... )
431 {
432  va_list arg;
433  DWORD id;
434 
435  PMsgBoxParams mbp = new MsgBoxParams( Title, _MAX_DBGMSG_, Flags );
436  mbp->pResult = pResult;
437 
438  va_start( arg, Fmt );
439  _vstprintf_s( (TSTR)mbp->lpszText, _MAX_DBGMSG_, Fmt, arg );
440  va_end( arg );
441 
442  TRACE( DP_DEBUG, _F("CreateThread (%s)\n"), Title );
443  HANDLE hThr = CreateThread( &DefSec, 0, __MBThread, mbp, 0, &id );
444  SleepEx( 0, true ); // Yield the rest of this thread's time slice..
445 
446  if (!hThr) delete mbp; // Failed.. Clean up so it doesn't leak.
447  else
448  {
449  while (!mbp->hBox) SleepEx( 10, true ); // Wait for MessageBox to initialize..
450  if (pResult) *pResult = (INT_PTR) mbp->hBox; // Return the window handle sideways.
451  }
452  return hThr;
453 }
454 
455 HANDLE __cdecl AsyncMsgBoxEx( // Parameter explanations are in the header.
456  HWND Owner, UINT Flags, CSTR Title,
457  HINSTANCE hInst, CSTR IconId, DWORD LangId,
458  DWORD_PTR HelpId, MSGBOXCALLBACK Callback,
459  PINT_PTR pResult, CSTR TextFmt, ...
460  )
461 {
462  va_list arg;
463  DWORD thrId;
464 
465  Title = mbox_Caption( Title, Owner );
466  PMsgBoxParams mbp = new MsgBoxParams( Title, _MAX_DBGMSG_, Flags );
467 
468  va_start( arg, TextFmt );
469  _vstprintf_s( (TSTR)mbp->lpszText, _MAX_DBGMSG_, TextFmt, arg );
470  va_end( arg );
471 
472  mbp->hwndOwner = Owner;
473  mbp->dwContextHelpId = HelpId;
474  mbp->dwLanguageId = LangId;
475  mbp->lpfnMsgBoxCallback = Callback;
476  mbp->pResult = pResult;
477 
478  // MessageBoxIndirect sets a standard icon based on MB_ICONMASK,
479  // so only setup lpszIcon/hInstance if a custom icon is specified.
480 
481  if (IconId)
482  {
483  mbp->hInstance = hInst;
484  mbp->lpszIcon = IconId;
485  mbp->dwStyle &= ~MB_SYSICONMASK;
486  mbp->dwStyle |= MB_USERICON;
487  }
488 
489  HANDLE hThr = CreateThread( &DefSec, 0, __MBThread, mbp, 0, &thrId );
490  SleepEx( 0, true ); // Yield the rest of this thread's time slice..
491 
492  if (!hThr) delete mbp; // Failed.. Clean up so it doesn't leak.
493  else
494  {
495  while (!mbp->hBox) SleepEx( 10, true ); // Wait for MessageBox to initialize..
496  if (pResult) *pResult = (INT_PTR) mbp->hBox; // Return the window handle.
497  }
498  return hThr;
499 }
500 
501 //-----------------------------------------------------------------------------
502 // Window routines
503 //-----------------------------------------------------------------------------
504 
505 // Get window height
506 
507 UINT GetWndHeight( HWND hWnd )
508 {
509  RECT R; GetWindowRect( hWnd, &R );
510  return R.bottom - R.top;
511 }
512 
513 // Get window width
514 
515 UINT GetWndWidth( HWND hWnd )
516 {
517  RECT R; GetWindowRect( hWnd, &R );
518  return R.right - R.left;
519 }
520 
521 // Get size of the window
522 
523 bool GetWndSize( HWND hWnd, SIZE* pSize )
524 {
525  RECT R = { 0,0,0,0 };
526  bool ok = bool_cast( GetWindowRect( hWnd, &R ));
527  if (ok) {
528  AbsToDimRect( &R );
529  //if (pSize) *pSize = *(SIZE*) &R.right; //<< May possibly beget misalignment issues...
530  if (pSize) *pSize = MkSize( R.right, R.bottom );
531  }
532  return ok;
533 }
534 
535 // Get pos of the window, in screen coords.
536 
537 bool GetWndPos( HWND hWnd, POINT* pPos )
538 {
539  RECT R = { 0,0,0,0 };
540  bool ok = bool_cast( GetWindowRect( hWnd, &R ));
541  if (ok && pPos) *pPos = MkPoint( R.left, R.top );
542  return ok;
543 }
544 
545 // Undoc: user32.dll, Vista+, Export=Name/Ordinal
546 // If hTrayApp is an eligible tray window, the returned rect
547 // contains the coords of the taskbar button.
548 
549 BOOL GetWindowMinimizeRect( HWND hTrayApp, RECT* pRect )
550 {
551  BOOL ok = false;
552  static BOOL (WINAPI *_GetWindowMinimizeRect)( HWND hTrayApp, RECT* pRect );
553  if (!_GetWindowMinimizeRect)
554  {
555  HMODULE hModule = GetOrLoadModule( _T("user32") );
556  if (hModule) (FARPROC&)_GetWindowMinimizeRect =
557  GetProcAddress( hModule, "GetWindowMinimizeRect" );
558  }
559  if (_GetWindowMinimizeRect) ok = _GetWindowMinimizeRect( hTrayApp, pRect );
560  return ok;
561 }
562 
563 bool CenterWindow( HWND hChild, HWND hParent )
564 {
565  RECT rCh, rPar, rWk;
566  int xNew, yNew;
567  bool ok = false;
568 
569  if (!hChild) SetLastError( ERROR_INVALID_PARAMETER );
570  else
571  {
572  if (!hParent) hParent = GetDesktopWindow();
573  GetWindowRect( hChild, &rCh );
574  GetWindowRect( hParent, &rPar );
575  AbsToDimRect( &rCh ); // right,bottom == width,height
576  AbsToDimRect( &rPar );
577  if (!SystemParametersInfo( SPI_GETWORKAREA, sizeof(RECT), &rWk, 0 ))
578  {
579  rWk.left = rWk.top = 0;
580  rWk.right = GetSystemMetrics( SM_CXSCREEN );
581  rWk.bottom = GetSystemMetrics( SM_CYSCREEN );
582  }
583 
584  // Calculate new X & Y position, then adjust for workarea
585  xNew = rPar.left + ((rPar.right - rCh.right) / 2);
586  if (xNew < rWk.left) xNew = rWk.left;
587  else if ((xNew + rCh.right) > rWk.right) xNew = rWk.right - rCh.right;
588 
589  yNew = rPar.top + ((rPar.bottom - rCh.bottom) / 2);
590  if (yNew < rWk.top) yNew = rWk.top;
591  else if ((yNew + rCh.bottom) > rWk.bottom) yNew = rWk.bottom - rCh.bottom;
592 
593  ok = bool_cast(
594  SetWindowPos( hChild,NULL, xNew,yNew, 0,0, SWP_NOSIZE| SWP_NOZORDER )
595  );
596  }
597  return ok;
598 }
599 
600 // Get the window rect of a control, in parent client coordinates.
601 
602 void GetChildWndRect( HWND hCtl, RECT* R )
603 {
604  GetWindowRect( hCtl, R );
605  MapWindowPoints( HWND_DESKTOP, GetParent( hCtl ), (LPPOINT) R, 2 );
606 }
607 
608 bool EnableChildWnd( HWND Owner, UINT Id, bool Enable )
609 {
610  HWND hchild = GetDlgItem( Owner, Id );
611  if (hchild) EnableWindow( hchild, Enable );
612  return hchild ? Enable : false;
613 }
614 
615 // Find child window with given Id.
616 
617 HWND GetChildWndWithId( HWND hParent, UINT ChildId )
618 {
619  HWND hCh = GetWindow( hParent, GW_CHILD );
620  while( hCh && ChildId != (UINT)GetWindowLong( hCh, GWL_ID )) {
621  hCh = GetWindow( hCh, GW_HWNDNEXT );
622  }
623  return hCh;
624 }
625 
626 // Icon convenience routine
627 
628 HICON WINAPI LoadSmallIcon( HINSTANCE hInst, CSTR Id )
629 {
630  return (HICON) LoadImage( hInst, Id, IMAGE_ICON, 16,16, LR_SHARED );
631 }
632 
633 //-----------------------------------------------------------------------------
634 // Menu routines
635 //-----------------------------------------------------------------------------
636 
637 // Load an internationalized menu resource
638 
639 HMENU LoadMenuEx( HMODULE hModule, CSTR Id, LANGID Language )
640 {
641  HMENU hMenu = NULL;
642  PVOID pRes = LoadCustomResourceEx( hInstance, Id, RT_MENU, Language );
643  if (!pRes) SetLastError( ERROR_INVALID_PARAMETER );
644  else hMenu = LoadMenuIndirect( (MENUTEMPLATE*) pRes );
645  return hMenu;
646 }
647 
648 // Find menu item by it's name.
649 
650 LPMENUITEMINFO GetMenuItemByName( HMENU hMenu, CSTR Name )
651 {
652  static TCHAR szBuf[80];
653  static MENUITEMINFO mii = { sizeof(MENUITEMINFO),0,0,0,0,0,0,0,0,0,0,0 };
654 
655  mii.fMask = MIIM_FTYPE | MIIM_STRING; // (On NT4 use MIIM_TYPE)
656  mii.dwTypeData = szBuf;
657 
658  for( int i=0, N = GetMenuItemCount( hMenu ); i < N; ++i )
659  {
660  mii.cch = dimof(szBuf) - 1; // Reserve 1 ch for terminating NUL.
661 
662  BOOL ok = GetMenuItemInfo( hMenu, i, TRUE, &mii );
663 
664  if (ok && BITS_SET( MFT_STRING, mii.fType )
665  && (_tcsicmp( mii.dwTypeData, Name ) == 0))
666  return &mii;
667  }
668  return NULL;
669 }
670 
671 // Get menu item id by it's name.
672 
673 int GetMenuItemIdByName( HMENU hMenu, CSTR Name )
674 {
675  LPMENUITEMINFO pmii = GetMenuItemByName( hMenu, Name );
676  return pmii ? pmii->wID : -1;
677 }
678 
679 // Get menu item data, if any..
680 
681 PVOID GetMenuItemData( HMENU hMenu, UINT Id )
682 {
683  PVOID pData = NULL;
684  MENUITEMINFO mii; IF_DEBUG( memset( &mii, 0, sizeof(mii) ));
685  mii.cbSize = sizeof(MENUITEMINFO);
686  mii.fMask = MIIM_DATA;
687  if (GetMenuItemInfo( hMenu, Id, false, &mii ))
688  pData = (PVOID) mii.dwItemData;
689  return pData;
690 }
691 
692 // Check/unckeck a menu item.
693 
694 bool SetMenuItemCheck( HMENU hMenu, UINT Id, bool Check )
695 {
696  #if 0
697  DWORD rc = CheckMenuItem( hMenu, Id, Check ? MF_CHECKED : MF_UNCHECKED );
698  return (rc != DWORD(-1));
699  #else // Supercedent: Doesn't clobber other state flag (if any)..
700  MENUITEMINFO mii; IF_DEBUG( memset( &mii, 0, sizeof(mii) ));
701 
702  mii.cbSize = sizeof(mii);
703  mii.fMask = MIIM_STATE;
704  mii.wID = Id;
705  BOOL ok = GetMenuItemInfo( hMenu, Id, false, &mii );
706  if (ok)
707  {
708  if (Check) mii.fState |= MFS_CHECKED; else mii.fState &= ~MFS_CHECKED;
709  // Note: MFS_UNCHECKED = MF_UNCHECKED = 0
710  ok = SetMenuItemInfo( hMenu, Id, false, &mii );
711  }
712  return bool_cast( ok );
713  #endif
714 }
715 
716 // Add a submenu with optional paraphernalia..
717 
719  HMENU hMenu, UINT Index, CSTR Text,
720  WORD Id, WORD State, PVOID Data, HBITMAP Image
721  )
722 {
723  DWORD err = 0;
724  MENUITEMINFO mii; IF_DEBUG( memset( &mii, 0, sizeof(mii) ));
725 
726  mii.hSubMenu = CreatePopupMenu();
727  if (mii.hSubMenu)
728  {
729  mii.cbSize = sizeof(MENUITEMINFO);
730  mii.fMask = MIIM_STRING| MIIM_FTYPE| MIIM_SUBMENU;
731  mii.fType = MFT_STRING;
732  mii.dwTypeData = (TSTR)Text;
733  if (Id)
734  {
735  mii.wID = Id;
736  mii.fMask |= MIIM_ID;
737  }
738  if (State)
739  {
740  mii.fState = State;
741  mii.fMask |= MIIM_STATE;
742  }
743  if (Data)
744  {
745  mii.dwItemData = (ULONG_PTR) Data;
746  mii.fMask |= MIIM_DATA;
747  }
748  if (Image)
749  {
750  mii.hbmpItem = Image;
751  mii.fMask |= MIIM_BITMAP;
752  }
753 
754  if (!InsertMenuItem( hMenu, Index, true, &mii ))
755  {
756  err = GetLastError(); // Hold error past DestroyMenu
757  DestroyMenu( mii.hSubMenu );
758  mii.hSubMenu = NULL;
759  }
760  if (err) SetLastError( err );
761  }
762  return mii.hSubMenu;
763 }
764 
765 // Add a menu item with optional paraphernalia..
766 
768  HMENU hMenu, UINT Index, CSTR Text, WORD cmdId,
769  WORD State, PVOID Data, HBITMAP Image
770  )
771 {
772  MENUITEMINFO mi; IF_DEBUG( memset( &mi, 0, sizeof(mi) ));
773  mi.cbSize = sizeof(mi);
774  mi.wID = cmdId;
775  if (!IsString( Text ))
776  {
777  mi.fMask = MIIM_FTYPE | MIIM_ID;
778  mi.fType = MFT_SEPARATOR;
779  }
780  else
781  {
782  mi.fMask = MIIM_STRING | MIIM_ID;
783  mi.dwTypeData = (TSTR) Text;
784  if (State)
785  {
786  mi.fState = State;
787  mi.fMask |= MIIM_STATE;
788  }
789  if (Data)
790  {
791  mi.dwItemData = (ULONG_PTR) Data;
792  mi.fMask |= MIIM_DATA;
793  }
794  if (Image)
795  {
796  mi.hbmpItem = Image;
797  mi.fMask |= MIIM_BITMAP;
798  }
799  }
800  return bool_cast( InsertMenuItem( hMenu, Index, true, &mi ));
801 }
802 
803 // Enumerate the items in a menu..
804 // typedef bool (__stdcall *PFnMenuItemAction)( HMENU hMenu, MENUITEMINFO* pInfo, PVOID Ctx );
805 
806 UINT EnumerateMenuItems( HMENU hMenu, PFnMenuItemAction Action, PVOID Ctx )
807 {
808  UINT nItems = 0; // Nr of items actually processed
809  MENUITEMINFO mii; IF_DEBUG( memset( &mii, 0, sizeof(mii) ));
810  static const short bufLen = 128;
811  TSTR textBuf = newStrBuf( bufLen ); // Not on the stack please!
812 
813  int count = GetMenuItemCount( hMenu );
814  for( int ix = 0; ix < count; ++ix )
815  {
816  mii.cbSize = sizeof(MENUITEMINFO);
817  mii.dwTypeData = textBuf;
818  mii.cch = bufLen;
819  mii.fMask = MIIM_ALL;
820  if (GetMenuItemInfo( hMenu, ix, true, &mii ))
821  {
822  if (!Action( hMenu, &mii, Ctx )) break;
823  ++nItems;
824  }
825  }
826 
827  deleteStr( textBuf );
828  return nItems;
829 }
830 
831 //-----------------------------------------------------------------------------
832 // Find, Load, and Lock a resource of arbitrary type
833 //-----------------------------------------------------------------------------
834 
835 // Note: Under Win32, resources are automatically unloaded on program termination.
836 // Calling UnlockResource and FreeResource is obsolete, according to MSDN.
837 // (Time was when we did it, to reduce the working set size.)
838 // See FreeResource..
839 
840 PVOID WINAPI LoadCustomResource( HMODULE hModule, CSTR Id, CSTR Type, UINT* pSize )
841 {
842  // FindResource, according to all sources, picks up the resource who's
843  // LANGUAGE statement (or fallback) matches the current user locale..
844 
845  HRSRC hrInfo = FindResource( hModule, Id, Type );
846  if (pSize && hrInfo) *pSize = SizeofResource( hModule, hrInfo );
847  HGLOBAL hRes = hrInfo ? LoadResource( hModule, hrInfo ) : NULL;
848  return hRes ? LockResource( hRes ) : NULL;
849 }
850 
851 PVOID WINAPI LoadCustomResourceEx(
852  HMODULE hModule, CSTR Id, CSTR Type, LANGID Language, UINT* pSize )
853 {
854  HRSRC hrInfo = FindResourceEx( hModule, Type, Id, Language );
855  if (!hrInfo) // If language (or finder fallback) not found ...
856  {
857  TRACE( DP_DEBUG, _F("FindResourceEx: LangId %u not found - %s.\n"), Language, SysErrorMsg() );
858  // Presumably these fallbacks were already tried by FindResourceEx,
859  // but have a go at it anyway, in case it didn't..
860  LANGID priLang = PRIMARYLANGID( Language );
861  LANGID usrLang = GetUserDefaultLangID();
862  LANGID sysLang = GetSystemDefaultLangID();
863 
864  if (priLang != Language)
865  hrInfo = FindResourceEx( hModule, Type, Id, priLang );
866 
867  if (!hrInfo && (usrLang != Language) )
868  hrInfo = FindResourceEx( hModule, Type, Id, usrLang );
869 
870  if (!hrInfo && (sysLang != Language) && (sysLang != usrLang))
871  hrInfo = FindResourceEx( hModule, Type, Id, sysLang );
872 
873  if (!hrInfo)
874  {
875  TRACE( DP_WARNING, _F("No fallback found, deferring to FindResource.\n") );
876  #if _DEBUG // Where the hell are we anyway..?
877  LCID Locale = GetThreadLocale();
878  Language = LANGIDFROMLCID( Locale );
879  priLang = PRIMARYLANGID( Language );
880  WORD subLang = SUBLANGID( Language );
881  TRACE( DP_VERBOSE,_F("Thread locale: %lu. LangId: %u (primary=%u, sub=%u).\n"),
882  Locale, Language, priLang, subLang
883  );
884  #endif
885  hrInfo = FindResource( hModule, Id, Type );
886  TRACE_IF( !hrInfo, DP_WARNING, _F("FindResource failed: %s.\n"), SysErrorMsg() );
887  }
888  }
889  // Finally, load and lock.
890 
891  if (pSize && hrInfo) *pSize = SizeofResource( hModule, hrInfo );
892  HGLOBAL hRes = hrInfo ? LoadResource( hModule, hrInfo ) : NULL;
893  return hRes ? LockResource( hRes ) : NULL;
894 }
895 
896 //-----------------------------------------------------------------------------
897 // Load a picture stored as a resource.
898 //-----------------------------------------------------------------------------
899 
900 IPicture* WINAPI LoadPictureResource( HMODULE hMod, CSTR Id, CSTR Type )
901 {
902  IPicture* pPic = NULL;
903 
904  // Use LoadCustomResource and SHCreateMemStream to get an IStream.
905  // Then use OleLoadPicture to get an IPicture.
906 
907  UINT cbData = 0;
908  PBYTE pData = (PBYTE) LoadCustomResource( hMod, Id, Type, &cbData );
909  if (pData)
910  {
911  IStream* pStrm = SHCreateMemStream( pData, cbData ); // Doesn't SetLastError
912  if (!pStrm) SetLastError( ERROR_RESOURCE_DATA_NOT_FOUND );
913  else
914  {
915  HRESULT rc = OleLoadPicture( pStrm, cbData, TRUE, IID_IPicture, (void**)&pPic );
916  if (FAILED( rc )) SetLastError( HRESULT_CODE( rc ));
917  TRACE_IF( FAILED(rc), DP_ERROR, _F("OleLoadPicture failed: %s\n"), SysErrorMsg( rc ));
918  pStrm->Release();
919  }
920  }
921  return pPic;
922 }
923 
924 //-----------------------------------------------------------------------------
925 // Use SHCreateStreamOnFile and OleLoadPicture to get an IPicture.
926 //-----------------------------------------------------------------------------
927 
928 IPicture* WINAPI LoadPictureFile( CSTR FName )
929 {
930  IPicture* pPic = NULL;
931 
932  ACCESS_MASK mode = STGM_READ| STGM_SHARE_DENY_WRITE;
933  IStream* pStrm = NULL;
934  HRESULT rc = SHCreateStreamOnFile( FName, mode, &pStrm );
935  if (!SUCCEEDED( rc )) SetLastError( HRESULT_CODE( rc ));
936  else
937  {
938  STATSTG stat; IF_DEBUG( memset( &stat, 0, sizeof(stat) ));
939  rc = pStrm->Stat( &stat, STATFLAG_NONAME );
940  TRACE_IF( stat.cbSize.HighPart, DP_WARNING, _F("Too large: %s\n"), FName );
941  if (SUCCEEDED( rc ) && !stat.cbSize.HighPart)
942  {
943  // OleLoadPicture won't handle an image larger than 32bit addressing permits.
944 
945  rc = OleLoadPicture( pStrm, stat.cbSize.LowPart, true, IID_IPicture, (void**)&pPic );
946 
947  if (!SUCCEEDED( rc )) SetLastError( HRESULT_CODE( rc ));
948  TRACE_IF( FAILED(rc), DP_ERROR, _F("OleLoadPicture failed: %s\n"), SysErrorMsg( rc ));
949  }
950  pStrm->Release();
951  }
952  return pPic;
953 }
954 
955 static POINT lpi = {0,0}; // Logical pixels per inch (on screen).
956 static const int hpi = 2540; // HiMetric units per inch.
957 
958 long WINAPI HiMetricToPix( long hiMetric )
959 {
960  // PONDER: Does assymetric lpi ever occur..? If so, this must be revised into cx/cy.
961  if (!lpi.x) GetScreenLPI( &lpi );
962  return MulDiv( hiMetric, lpi.x, hpi );
963 }
964 
965 long WINAPI PixToHiMetric( long Pix )
966 {
967  // PONDER: Does assymetric lpi ever occur..? If so, this must be revised into cx/cy.
968  if (!lpi.x) GetScreenLPI( &lpi );
969  return MulDiv( Pix, hpi, lpi.x );
970 }
971 
972 //-----------------------------------------------------------------------------
973 // Paint an IPicture on a normal MM_TEXT mode HDC.
974 // cx, cy = Image size in pixels. If 0, the full image size is computed.
975 //-----------------------------------------------------------------------------
976 
977 void WINAPI PaintPicture( IPicture* pPic, HDC hdc, int x, int y, int cx, int cy )
978 {
979  LONG wIm, hIm; // HiMetric image size
980 
981  pPic->get_Width( &wIm );
982  pPic->get_Height( &hIm );
983  // Convert himetric size to pixels (if no cx/cy given)
984  if (!lpi.x) GetScreenLPI( &lpi );
985  if (!cx) cx = MulDiv( wIm, lpi.x, hpi );
986  if (!cy) cy = MulDiv( hIm, lpi.y, hpi );
987 
988  // By default, HDC has MM_TEXT mapping (IPicture assumes MM_HIMETRIC),
989  // so flip the cy sign, and set y to the bottom left image pos.
990  // Don't bother with SetMapMode( hdc,MM_HIMETRIC ), since that would
991  // seriously complicate all other drawing, just mollycoddle IPic a bit.
992 
993  pPic->Render( hdc, x, y+cy, cx,-(cy+1), 0,0, wIm,hIm, NULL );
994 }
995 
996 // CHANGE LOG:
997 // LN 2022 Corrected flawed imw/imh logic.
998 
999 bool WINAPI PaintPictureEx( IPicture* pPic,
1000  HDC hdc, long x, long y, long cx, long cy,
1001  long imx, long imy, long imw, long imh, PRECT prMeta
1002  )
1003 {
1004  long imgWidth, imgHeight;
1005  bool ok = ((pPic != NULL) && (hdc != NULL));
1006  if (!ok) SetLastError( ERROR_INVALID_PARAMETER );
1007  else
1008  {
1009  HRESULT rc;
1010  ok = SUCCEEDED( rc = pPic->get_Width( &imgWidth ));
1011  if (!ok) SetLastError( HRESULT_CODE( rc ));
1012  else
1013  {
1014  ok = SUCCEEDED( rc = pPic->get_Height( &imgHeight ));
1015  if (!ok) SetLastError( HRESULT_CODE( rc ));
1016  else
1017  {
1018  if (imx) imx = PixToHiMetric( imx );
1019  if (imy) imy = PixToHiMetric( imy );
1020  if (!imw) imw = imgWidth; else imw = PixToHiMetric( imw );
1021  if (!imh) imh = imgHeight; else imw = PixToHiMetric( imh );;
1022  // Sacrifice a tiny reconversion CPU time to avoid kludgy assignment logic above..
1023  if (!cx) cx = HiMetricToPix( imw );
1024  if (!cy) cy = HiMetricToPix( imh );
1025 
1026  // By default, HDC has MM_TEXT mapping (IPicture assumes MM_HIMETRIC),
1027  // so flip the cy sign, and set y to the bottom left image pos.
1028  // Don't bother with SetMapMode( hdc,MM_HIMETRIC ), since that would
1029  // seriously complicate all other drawing, just mollycoddle IPic a bit.
1030 
1031  // NOTE: IPicture::Render expects x,y,cx,cy in pixels
1032  // and imx,imy,imw,imh in himetric coords!
1033 
1034  ok = SUCCEEDED( rc = pPic->Render(
1035  hdc, x, y+cy, cx,-(cy+1), imx, imy, imw, imh, prMeta
1036  ));
1037  if (!ok) SetLastError( HRESULT_CODE( rc ));
1038  }
1039  }
1040  }
1041  return ok;
1042 }
1043 
1044 //-----------------------------------------------------------------------------
1045 // More window routines
1046 //-----------------------------------------------------------------------------
1047 
1048 // Create window by means of a CREATESTRUCT
1049 
1050 HWND CreateWindowIndirect( LPCREATESTRUCT pc )
1051 {
1052  return CreateWindowEx(
1053  pc->dwExStyle, pc->lpszClass, pc->lpszName, pc->style,
1054  pc->x, pc->y, pc->cx, pc->cy,
1055  pc->hwndParent, pc->hMenu, pc->hInstance, pc->lpCreateParams
1056  );
1057 }
1058 
1059 // Execute a modal internationalized dialog.
1060 
1062  HINSTANCE hInstance, CSTR Template, HWND hParent,
1063  DLGPROC DlgProc, LPARAM lParam, LANGID Language
1064  )
1065 {
1066  INT_PTR rc = -1;
1067  PVOID pRes = LoadCustomResourceEx( hInstance, Template, RT_DIALOG, Language );
1068  if (!pRes) SetLastError( ERROR_INVALID_PARAMETER );
1069  else rc = DialogBoxIndirectParam(
1070  hInstance, (LPCDLGTEMPLATE)pRes, hParent, DlgProc, lParam
1071  );
1072  return rc;
1073 }
1074 
1075 // Create a modeless internationalized dialog.
1076 
1078  HINSTANCE hInstance, CSTR Template, HWND hParent,
1079  DLGPROC DlgProc, LPARAM lParam, LANGID Language
1080  )
1081 {
1082  HWND hDlg = NULL;
1083  PVOID pRes = LoadCustomResourceEx( hInstance, Template, RT_DIALOG, Language );
1084  if (!pRes) SetLastError( ERROR_INVALID_PARAMETER );
1085  else hDlg = CreateDialogIndirectParam(
1086  hInstance, (LPCDLGTEMPLATE)pRes, hParent, DlgProc, lParam
1087  );
1088  return hDlg;
1089 }
1090 
1091 // Compute required window size for a given client size
1092 // TODO: Be kind and make RECT versions of these two..
1093 
1094 bool GetRequiredWindowSize( HWND hWnd, IN const PSIZE pClient, OUT PSIZE pWindow )
1095 {
1096  DWORD style = GWL( hWnd, STYLE );
1097  DWORD xstyle = GWL( hWnd, EXSTYLE );
1098  HMENU menu = GetMenu( hWnd );
1099  RECT rWnd = MkRect( 0,0, pClient->cx, pClient->cy );
1100  BOOL ok = AdjustWindowRectEx( &rWnd, style, (menu != NULL), xstyle );
1101  AbsToRelRect( &rWnd ); // Make it zero-based..
1102  pWindow->cx = rWnd.right;
1103  pWindow->cy = rWnd.bottom;
1104  return bool_cast( ok );
1105 }
1106 
1107 // Get effective client size for a given window size
1108 
1109 bool GetWindowClientSize( HWND hWnd, IN const PSIZE pWindow, OUT PSIZE pClient )
1110 {
1111  DWORD style = GWL( hWnd, STYLE );
1112  DWORD xstyle = GWL( hWnd, EXSTYLE );
1113  HMENU menu = GetMenu( hWnd );
1114  RECT rWnd = MkRect( 0,0, pWindow->cx, pWindow->cy );
1115  BOOL ok = AdjustWindowRectEx( &rWnd, style, (menu != NULL), xstyle );
1116  AbsToRelRect( &rWnd ); // Make it zero-based (w,h)..
1117  long cxDiff = rWnd.right - pWindow->cx;
1118  long cyDiff = rWnd.bottom - pWindow->cy;
1119  pClient->cx = pWindow->cx - cxDiff;
1120  pClient->cy = pWindow->cy - cyDiff;
1121  return bool_cast( ok );
1122 }
1123 
1124 // Refresh window
1125 
1126 bool RefreshWnd( HWND hwnd )
1127 {
1128  InvalidateRect( hwnd, NULL, TRUE );
1129  return bool_cast( UpdateWindow( hwnd ));
1130 }
1131 
1132 // Redraw all or part of window
1133 
1134 bool RedrawWnd( HWND hwnd, UINT flags )
1135 {
1136  return bool_cast( ::RedrawWindow( hwnd, NULL, NULL, flags ));
1137 }
1138 
1139 bool RedrawWndRect( HWND hwnd, PRECT prect, UINT flags )
1140 {
1141  return bool_cast( ::RedrawWindow( hwnd, prect, NULL, flags ));
1142 }
1143 
1144 bool RedrawWndRgn( HWND hwnd, HRGN hrgn, UINT flags )
1145 {
1146  return bool_cast( ::RedrawWindow( hwnd, NULL, hrgn, flags ));
1147 }
1148 
1149 // Move window without resizing or Z order change
1150 
1151 bool MoveWnd( HWND hwnd, int X, int Y, bool repaint )
1152 {
1153  UINT flags = SWP_NOSIZE| SWP_NOZORDER| (repaint ? 0:SWP_NOREDRAW);
1154  return bool_cast( SetWindowPos( hwnd, NULL, X, Y, 0, 0, flags ));
1155 }
1156 
1157 // Resize window without moving or changing Z order
1158 
1159 bool ResizeWnd( HWND hwnd, int W, int H, bool repaint )
1160 {
1161  UINT flags = SWP_NOMOVE| SWP_NOZORDER| (repaint ? 0:SWP_NOREDRAW);
1162  return bool_cast( SetWindowPos( hwnd, NULL, 0, 0, W, H, flags ));
1163 }
1164 
1165 // SetParent need some cotton-gloving to succeed in special cases
1166 
1167 HWND SetParentWnd( HWND wnd, HWND newParent )
1168 {
1169  SetLastError( 0 ); // Since we might return NULL as a *valid result*.
1170  HWND parent = GetParent( wnd );
1171  if (GetLastError() != 0) return NULL; // Failed: Cannot get parent
1172  if (newParent == parent) return parent; // Already (NB: NULL is valid parent)
1173 
1174  DWORD style = GetWndStyle( wnd );
1175  DWORD save = style;
1176 
1177  if (newParent != NULL && parent == NULL)
1178  {
1179  // If changing from top level, must change window style too
1180 
1181  style &= ~(WS_POPUP| WS_OVERLAPPED);
1182  style |= WS_CHILD; // Set this style *before* SetParent
1183  SetWndStyle( wnd, style );
1184  }
1185 
1186  SetParent( wnd, newParent ); // Try to change parent
1187  if (GetLastError() != 0)
1188  {
1189  if (style != save) SetWndStyle( wnd, save ); // Restore changed style
1190  return NULL; // Failed: Cannot set parent
1191  }
1192 
1193  if (newParent == NULL && parent != NULL)
1194  {
1195  // If changing to top level, must change window style too
1196 
1197  style &= ~WS_CHILD;
1198  style |= WS_OVERLAPPED; // Set this style *after* SetParent
1199  SetWndStyle( wnd, style );
1200  }
1201  return parent; // Return previous parent
1202 }
1203 
1204 // A combo has 3 window handles, one for the aggregate, and two handles
1205 // for the editor and listbox parts. Retrieve the editor and list handles.
1206 
1207 #define COMBO_LISTCLASS _T("ComboLBox")
1208 #define COMBO_EDITCLASS _T("Edit")
1209 
1210 bool IsWndClass( HWND hWnd, CSTR clsName )
1211 {
1212  TCHAR buf[ 80 ];
1213  bool ok = bool_cast( GetClassName( hWnd, buf, dimof(buf) ));
1214  if (ok) ok = (_tcsicmp( buf, clsName ) == 0);
1215  return ok;
1216 }
1217 
1218 HWND GetComboEditor( HWND hCombo )
1219 {
1220  HWND hSub = GetWindow( hCombo, GW_CHILD );
1221  if (IsWndClass( hSub, COMBO_EDITCLASS )) return hSub;
1222  return GetWindow( hSub, GW_HWNDNEXT );
1223 }
1224 
1225 HWND GetComboList( HWND hCombo ) // FIXME: Malfunc on W7sp1 !
1226 {
1227  HWND hSub = GetWindow( hCombo, GW_CHILD );
1228  if (IsWndClass( hSub, COMBO_LISTCLASS )) return hSub;
1229  return GetWindow( hSub, GW_HWNDNEXT );
1230 }
1231 
1232 CSTR GetWndClassName( HWND hWnd ) // Get the window's class name
1233 {
1234  static __thread_local TCHAR buf[ 80 ];
1235  if (!GetClassName( hWnd, buf, dimof(buf) )) buf[0] = 0;
1236  return buf;
1237 }
1238 
1239 //-----------------------------------------------------------------------------
1240 // Controls ...
1241 //-----------------------------------------------------------------------------
1242 
1243 double GetWndReal( HWND hCtl )
1244 {
1245  TCHAR sBuf[64], *pEnd;
1246  int len = GetWindowText( hCtl, sBuf, dimof(sBuf) );
1247  return (len ? _tcstod( sBuf, &pEnd ) : HUGE_VAL); // NB: HUGE_VAL comply w strtod error.
1248 }
1249 double GetDlgItemReal( HWND hDlg, UINT Id )
1250 {
1251  return GetWndReal( GetDlgItem( hDlg, Id ));
1252 }
1253 
1254 bool SetWndReal( HWND hCtl, double Value, BYTE nDeci, CSTR Suffix )
1255 {
1256  static CCSTR FmtSuff = _T("%.*f %s"), FmtNoSuff = _T("%.*f");
1257  TCHAR sBuf[64];
1258  CSTR Fmt = Suffix ? FmtSuff : FmtNoSuff;
1259  _stprintf_s( sBuf, dimof(sBuf), Fmt, nDeci, Value, Suffix );
1260  return bool_cast( SetWindowText( hCtl, sBuf ));
1261 }
1262 bool SetDlgItemReal( HWND hDlg, UINT Id, double Value, BYTE nDeci, CSTR Suffix )
1263 {
1264  return SetWndReal( GetDlgItem( hDlg, Id ), Value, nDeci, Suffix );
1265 }
1266 
1267 //== Multiple Document Interface ==--------------------------------------------
1268 
1269 HWND GetMDIClient( HWND hMdiFrame )
1270 {
1271  HWND W = GetWindow( hMdiFrame, GW_CHILD );
1272  while( W )
1273  {
1274  if (IsWndClass( W, MDI_CLIENTCLASS )) return W;
1275  W = GetWindow( W, GW_HWNDNEXT );
1276  }
1277  return NULL;
1278 }
1279 
1280 //== Buttons ==----------------------------------------------------------------
1281 
1282 bool ButtonChecked( HWND hBtn )
1283 {
1284  return (Button_GetCheck( hBtn ) == BST_CHECKED);
1285 }
1286 bool ButtonCtrlChecked( HWND hDlg, UINT Id )
1287 {
1288  return ButtonChecked( GetDlgItem( hDlg,Id ));
1289 }
1290 
1291 bool CheckButton( HWND hBtn, bool Check )
1292 {
1293  Button_SetCheck( hBtn, Check ? BST_CHECKED : BST_UNCHECKED );
1294  return Check;
1295 }
1296 bool CheckButtonCtrl( HWND hDlg, UINT Id, bool Check )
1297 {
1298  return CheckButton( GetDlgItem( hDlg,Id ), Check );
1299 }
1300 
1301 //== Listboxes ==--------------------------------------------------------------
1302 
1303 int __cdecl AddListString( HWND hLB, CSTR Fmt, ... )
1304 {
1305  TCHAR sbuf[256];
1306  va_list va;
1307 
1308  va_start( va, Fmt );
1309  _vstprintf_s( sbuf, dimof(sbuf), Fmt, va );
1310  va_end( va );
1311 
1312  return ListBox_AddString( hLB, sbuf );
1313 }
1314 
1315 int AddListItem( HWND hLB, CSTR Text, LPARAM Data )
1316 {
1317  int ix = ListBox_FindStringExact( hLB, -1, Text );
1318  if (ix < 0)
1319  {
1320  ix = ListBox_AddString( hLB, Text );
1321  if (ix >= 0) ListBox_SetItemData( hLB, ix, Data );
1322  }
1323  return ix;
1324 }
1325 
1326 //== Combo boxes ==------------------------------------------------------------
1327 
1328 int __cdecl AddComboString( HWND hCB, CSTR Fmt, ... )
1329 {
1330  TCHAR sbuf[256];
1331  va_list va;
1332 
1333  va_start( va, Fmt );
1334  _vstprintf_s( sbuf, dimof(sbuf), Fmt, va );
1335  va_end( va );
1336 
1337  return ComboBox_AddString( hCB, sbuf );
1338 }
1339 
1340 int AddComboItem( HWND hCB, CSTR Text, LPARAM Data )
1341 {
1342  int ix = ComboBox_FindStringExact( hCB, -1, Text );
1343  if (ix < 0)
1344  {
1345  ix = ComboBox_AddString( hCB, Text );
1346  if (ix >= 0) ComboBox_SetItemData( hCB, ix, Data );
1347  }
1348  return ix;
1349 }
1350 
1351 //== Status bars ==------------------------------------------------------------
1352 
1353 //bool __cdecl SetStatusParts( HWND hStat, UINT nParts, ... ) // Original
1354 //{
1355 // va_list va;
1356 // bool simple = (nParts < 2);
1357 // bool ok = simple;
1358 // SendMessage( hStat, SB_SIMPLE, simple, 0 );
1359 // if (!simple)
1360 // {
1361 // va_start( va, nParts );
1362 // int ix, w, *parts = new int[ nParts ];
1363 // parts[ 0 ] = va_arg( va, int );
1364 // for( ix=1; ix < (int)nParts; ++ix )
1365 // {
1366 // w = va_arg( va, int );
1367 // parts[ ix ] = (w == -1) ? w : parts[ ix-1 ] + w;
1368 // }
1369 // ok = bool_cast( SB_SetParts( hStat, nParts, (LPARAM)parts ));
1370 //
1371 // delete[] parts;
1372 // va_end( va );
1373 // }
1374 // return ok;
1375 //}
1376 
1377 bool __cdecl SetStatusParts( HWND hStat, UINT nParts, ... ) // Revised to use the new SetStatusWidths API...
1378 {
1379  va_list va;
1380  bool simple = (nParts < 2);
1381  bool ok = simple;
1382  SendMessage( hStat, SB_SIMPLE, simple, 0 );
1383  if (!simple)
1384  {
1385  int *parts = new int[ nParts ];
1386 
1387  va_start( va, nParts );
1388  int *part = parts, n = nParts;
1389  while( n-- ) *part++ = va_arg( va, int ); //for( UINT ix = 0; ix < nParts; ++ix ) parts[ ix ] = va_arg( va, int );
1390  va_end( va );
1391 
1392  ok = SetStatusWidths( hStat, nParts, parts );
1393  delete[] parts;
1394  }
1395  return ok;
1396 }
1397 
1398 bool __cdecl SetStatusWidths( HWND hStat, UINT nParts, int* Width )
1399 {
1400  bool simple = (nParts < 2);
1401  bool ok = simple;
1402  SendMessage( hStat, SB_SIMPLE, simple, 0 );
1403  if (!simple)
1404  {
1405  register int* pos = Width + 1;
1406  // Note FYI: Using pointer access to the array
1407  // generates faster machine code than indexing the array.
1408  for( UINT ix = 1; ix < nParts; ++ix, ++pos )
1409  {
1410  if (*pos != -1) *pos += *(pos - 1);
1411  else // -1
1412  {
1413  nParts = ix + 1; // In case we're cut short by -1.
1414  break; // Whether we reached nParts or not.
1415  }
1416  }
1417  ok = bool_cast( SB_SetParts( hStat, nParts, (LPARAM) Width ));
1418  }
1419  return ok;
1420 }
1421 
1422 bool __cdecl SetStatusText( HWND hStat, UINT Part, CSTR Fmt, ... )
1423 {
1424  static __thread_local TCHAR sbuf[ MAX_PATH ];
1425  va_list va;
1426 
1427  *sbuf = SPACE; // Status text looks better with a little left padding.
1428  va_start( va, Fmt );
1429  _vstprintf_s( &sbuf[1], dimof(sbuf)-1, Fmt, va );
1430  va_end( va );
1431  return bool_cast( SB_SetText( hStat, Part, sbuf ));
1432 }
1433 
1434 HWND CreateStatusbar( HWND hParent, UINT Id, CSTR Text, UINT Style )
1435 {
1436  static const WORD STAT_HEIGHT = 24; // Incl static edge
1437  static const UINT UNSUPP = WS_POPUP| CCS_TOP| CCS_LEFT| CCS_RIGHT;
1438  RECT r;
1439 
1440  // Resize the parent to make room for a status bar ...
1441 
1442  GetWindowRect( hParent, &r );
1443  r.right -= r.left; r.bottom -= r.top;
1444  r.bottom += STAT_HEIGHT;
1445  SetWindowPos( hParent, NULL, 0,0, r.right, r.bottom, SWP_NOZORDER| SWP_NOMOVE );
1446 
1447  // And create the statusbar window ...
1448 
1449  Style = (Style & ~UNSUPP) | (WS_CHILD| WS_VISIBLE| CCS_BOTTOM); // Must be so.
1450  HINSTANCE hInst = GetWindowInstance( hParent );
1451  GetClientRect( hParent, &r );
1452 
1453  return CreateWindowEx( WS_EX_STATICEDGE, STATUSCLASSNAME,
1454  Text, Style, 0, r.bottom - STAT_HEIGHT, r.right, STAT_HEIGHT,
1455  hParent, HMENU(UINT_PTR( Id )), hInst, NULL
1456  );
1457 }
1458 
1459 //== List controls ==----------------------------------------------------------
1460 
1461 UINT ListView_ForEach( HWND hLv, PFLvItemAction Action, PVOID pCtx )
1462 {
1463  static __thread_local TCHAR Text[256];
1464 
1465  UINT N, nItems, ix;
1466  LVITEM lvi; IF_DEBUG( memset( &lvi, 0, sizeof(lvi) ));
1467 
1468  N = 0;
1469  nItems = ListView_GetItemCount( hLv );
1470  if (nItems)
1471  {
1472  for( ix = 0; ix < nItems; ++ix )
1473  {
1474  lvi.mask = LVIF_TEXT| LVIF_PARAM| LVIF_IMAGE| LVIF_STATE;
1475  lvi.iItem = ix;
1476  lvi.iSubItem = 0;
1477  lvi.pszText = Text;
1478  lvi.cchTextMax = dimof(Text);
1479  lvi.stateMask = UINT(-1);
1480 
1481  if (ListView_GetItem( hLv, &lvi ))
1482  {
1483  if (!Action( hLv, &lvi, pCtx )) break;
1484  N++;
1485  }
1486  }
1487  }
1488  return N;
1489 }
1490 
1491 //== Tree controls ==----------------------------------------------------------
1492 
1493 bool TreeView_GetItemText( HWND hTree, HTREEITEM hItem, TSTR Buf, UINT bufLen )
1494 {
1495  BOOL ok = (hTree && hItem && Buf && bufLen);
1496  if (!ok) SetLastError( ERROR_INVALID_PARAMETER );
1497  else
1498  {
1499  TVITEM tvi;// = { TVIF_TEXT, hItem };
1500  IF_DEBUG( memset( &tvi, 0, sizeof(tvi) ));
1501  tvi.mask = TVIF_TEXT;
1502  tvi.hItem = hItem;
1503  tvi.pszText = Buf;
1504  tvi.cchTextMax = bufLen;
1505  ok = TreeView_GetItem( hTree, &tvi );
1506  if (!ok) *Buf = 0;
1507  else if (tvi.pszText != Buf) _tcscpy_s( Buf, bufLen, tvi.pszText );
1508  // [MSDN:TVM_GETITEM] "The returned text will not necessarily be stored in
1509  // the original buffer passed by the application. It is possible that pszText
1510  // will point to text in a new buffer rather than place it in the old buffer."
1511  }
1512  return bool_cast( ok );
1513 }
1514 
1515 //== Trackbar ==---------------------------------------------------------------
1516 
1517 static const UINT _SI_SIZE = sizeof(SCROLLINFO);
1518 
1519 bool GetTrackbarInfo( HWND hCtl, LPSCROLLINFO psi )
1520 {
1521  bool ok = ((psi->cbSize == _SI_SIZE) && !IsBadWritePtr( psi, _SI_SIZE ));
1522  if (!ok) SetLastError( ERROR_INVALID_PARAMETER );
1523  else
1524  {
1525  if (psi->fMask & SIF_PAGE) psi->nPage = (UINT) SendMessage( hCtl, TBM_GETPAGESIZE, 0,0 );
1526  if (psi->fMask & SIF_RANGE)
1527  {
1528  psi->nMin = (int) SendMessage( hCtl, TBM_GETRANGEMIN, 0,0 );
1529  psi->nMax = (int) SendMessage( hCtl, TBM_GETRANGEMAX, 0,0 );
1530  }
1531  bool getPos = bool_cast( psi->fMask & SIF_POS );
1532  bool getTrkPos = bool_cast( psi->fMask & SIF_TRACKPOS );
1533  if (getPos || getTrkPos)
1534  {
1535  int pos = (int) SendMessage( hCtl, TBM_GETPOS, 0,0 );
1536  if (getTrkPos) psi->nTrackPos = pos;
1537  if (getPos) psi->nPos = pos;
1538  }
1539  }
1540  return ok;
1541 }
1542 
1543 bool SetTrackbarInfo( HWND hCtl, LPSCROLLINFO psi, bool Redraw )
1544 {
1545  bool ok = ((psi->cbSize == _SI_SIZE) && !IsBadReadPtr( psi, _SI_SIZE ));
1546  if (!ok) SetLastError( ERROR_INVALID_PARAMETER );
1547  else
1548  {
1549  SendMessage( hCtl, TBM_SETLINESIZE, 0, 1 ); // Scrollbar compatible default
1550 
1551  if (psi->fMask & SIF_PAGE) SendMessage( hCtl, TBM_SETPAGESIZE, 0, psi->nPage );
1552  if (psi->fMask & SIF_RANGE)
1553  {
1554  SendMessage( hCtl, TBM_SETRANGEMIN, false, psi->nMin );
1555  SendMessage( hCtl, TBM_SETRANGEMAX, Redraw, psi->nMax );
1556  }
1557  if (psi->fMask & SIF_POS) SendMessage( hCtl, TBM_SETPOS, Redraw, psi->nPos );
1558  }
1559  return ok;
1560 }
1561 
1562 //== Imagelist ==--------------------------------------------------------------
1563 
1565  HINSTANCE hInst, UINT Id, LPCOLORMAP Map, UINT nMap,
1566  UINT cxImg, UINT Flags, UINT nGrow
1567  )
1568 {
1569  HIMAGELIST hIml = NULL;
1570  HBITMAP hBmp = CreateMappedBitmap( hInstance, Id, 0, Map, nMap );
1571  if (hBmp)
1572  {
1573  BITMAP bm; GetObject( hBmp, sizeof(BITMAP), &bm );
1574  UINT imgCount = bm.bmWidth / cxImg;
1575  hIml = ImageList_Create( cxImg, bm.bmHeight, Flags, imgCount, nGrow );
1576  ImageList_Add( hIml, hBmp, NULL );
1577  DeleteBitmap( hBmp );
1578  }
1579  return hIml;
1580 }
1581 
1582 //== Toolbar ==----------------------------------------------------------------
1583 
1584 // The toolbars and rebars have so many quirks that I lost count.. :/
1585 // That the MSDN documentation for them is dismally incomplete doesn't help one iota.
1586 // Caveat Emptor
1587 
1588 static const DWORD TBSTYLE_EX_MASK =
1589  TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS
1590  | TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_DOUBLEBUFFER;
1591 
1592 //static SIZES _smSize( DWORD dw ) { return LITERAL( SIZES, dw ); }
1593 //static void _trace_BarExt( HWND hBar, CSTR Where, int ww, int hh, int cxBtn, int cyBtn )
1594 //{
1595 // SIZES btnExt, btnPad; SIZE barExt;
1596 // btnExt = _smSize( (DWORD)SendMessage( hBar, TB_GETBUTTONSIZE, 0,0 ));
1597 // btnPad = _smSize( (DWORD)SendMessage( hBar, TB_GETPADDING, 0,0 ));
1598 // GetWndSize( hBar, &barExt );
1599 // TRACE( DP_DEBUG, _F("%s: cxBtn=%u(%u), cyBtn=%u(%u), btnPad={%u,%u}, barExt={%u(%u),%u(%u)}\n"),
1600 // Where, btnExt.cx, cxBtn, btnExt.cy, cyBtn, btnPad.cx, btnPad.cy, barExt.cx, ww, barExt.cy, hh
1601 // );
1602 //}
1603 
1605  HWND hParent, UINT Id, UINT x, UINT y, UINT w, UINT h,
1606  UINT cxBtn, UINT cyBtn, HIMAGELIST hImages, LPTBBUTTON Buttons, UINT nButtons,
1607  DWORD Style, DWORD ExStyle
1608  )
1609 {
1610  HWND hBar = NULL;
1611  if (!Buttons || !nButtons) SetLastError( ERROR_INVALID_PARAMETER );
1612  else
1613  {
1614  HINSTANCE hInst = (HINSTANCE) GWLP( hParent, HINSTANCE );
1615  DWORD wsEx = ExStyle & ~TBSTYLE_EX_MASK; // WS_EX_nn
1616  DWORD tbEx = ExStyle & TBSTYLE_EX_MASK; // TBSTYLE_EX_nn
1617 
1618  hBar = CreateWindowEx( wsEx, TOOLBARCLASSNAME,
1619  S_BLANK, Style, x, y, w, h, hParent, (HMENU)(UINT_PTR) Id, hInst, NULL
1620  );
1621  if (hBar)
1622  {
1623  if (tbEx) SendMessage( hBar, TB_SETEXTENDEDSTYLE, 0, tbEx );
1624  if (hImages) SendMessage( hBar, TB_SETIMAGELIST, 0, LPARAM( hImages ));
1625  #if 1
1626  int cxIm, cyIm; // Better safe than sorry..
1627  ImageList_GetIconSize( hImages, &cxIm, &cyIm );
1628  SendMessage( hBar, TB_SETBITMAPSIZE, 0, MAKELPARAM( cxIm, cyIm ));
1629  #endif
1630  SendMessage( hBar, TB_SETINDENT, 2,0 ); // Indent the first button 2 pix..
1631  SendMessage( hBar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0 );
1632  SendMessage( hBar, TB_ADDBUTTONS, nButtons, LPARAM( Buttons ));
1633  SendMessage( hBar, TB_SETBUTTONSIZE, 0, MAKELPARAM( cxBtn, cyBtn )); // NOT HONORED
1634  //SendMessage( hBar, TB_SETBUTTONWIDTH, 0, MAKELPARAM( cxBtn, cxBtn*5 )); // NOT HONORED
1635  }
1636  }
1637  return hBar;
1638 }
1639 
1641  HWND hParent, UINT Id, UINT x, UINT y, UINT w, UINT h,
1642  UINT imgType, LPTBBUTTON Buttons, UINT nButtons, DWORD Style, DWORD ExStyle
1643  )
1644 {
1645  HWND hBar = NULL;
1646  if ((imgType > 9) || (imgType & 1)) // Large toolbuttons and IE travel images seem dysfunctional.. :(
1647  SetLastError( ERROR_INVALID_PARAMETER );
1648  else
1649  {
1650  HINSTANCE hInst = GetWindowInstance( hParent );
1651  DWORD wsEx = ExStyle & ~TBSTYLE_EX_MASK;
1652  DWORD tbEx = ExStyle & TBSTYLE_EX_MASK;
1653  UINT cxyBtn = (h - 2); // Sadly, the button size is disregarded... we might as well say 2px here :(
1654 
1655  hBar = CreateWindowEx( wsEx, TOOLBARCLASSNAME,
1656  S_BLANK, Style, x, y, w, h, hParent, (HMENU)(UINT_PTR) Id, hInst, NULL
1657  );
1658  SendMessage( hBar, TB_SETEXTENDEDSTYLE, 0, tbEx );
1659  SendMessage( hBar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0 );
1660  SendMessage( hBar, TB_SETINDENT, 2, 0 );
1661  SendMessage( hBar, TB_LOADIMAGES, imgType, LPARAM( HINST_COMMCTRL ));
1662  SendMessage( hBar, TB_SETBUTTONSIZE, 0, MAKELPARAM( cxyBtn, cxyBtn ));
1663  SendMessage( hBar, TB_ADDBUTTONS, nButtons, LPARAM( Buttons ));
1664  SendMessage( hBar, TB_SETBUTTONSIZE, 0, MAKELPARAM( cxyBtn, cxyBtn )); // NOT HONORED... :(
1665  }
1666  return hBar;
1667 }
1668 
1669 //== Rebar ==------------------------------------------------------------------
1670 
1671 WORD RebarBandInfoSize() // Life saver!
1672 {
1673  WORD size;
1674  UINT ver = GetDLLVersion( _T("comctl32.dll") );
1675 
1676  if (ver < PACKVERSION( 4,71 )) // initial guesstimate..
1677  size = CCSIZEOF_STRUCT( REBARBANDINFO, wID );
1678  else if (ver < PACKVERSION( 6,0 ))
1679  size = CCSIZEOF_STRUCT( REBARBANDINFO, cxHeader ); // Yup..
1680  #if (_WIN32_WINNT >= 0x0600)
1681  else // >= 6.0
1682  size = CCSIZEOF_STRUCT( REBARBANDINFO, uChevronState );
1683  //= sizeof(REBARBANDINFO);
1684  #endif
1685  return size;
1686 }
1687 //WORD RebarBandInfoSize()
1688 //{
1689 // WORD size = sizeof(REBARBANDINFO);
1690 // //or: WORD size = CCSIZEOF_STRUCT( REBARBANDINFO, uChevronState );
1691 // UINT ver = GetDLLVersion( "comctl32.dll" );
1692 // if (ver < PACKVERSION( 6,0 ))
1693 // #if (_WIN32_IE < 0x0400) // comctl32 4.71... wasn't it..?
1694 // size = REBARBANDINFOA_V3_SIZE;
1695 // #else
1696 // size = CCSIZEOF_STRUCT( REBARBANDINFO, cxHeader );
1697 // #endif
1698 // return size;
1699 //}
1700 
1701 //==---------------------------------------------------------------------------
1702 // EOF
int __cdecl AddListString(HWND hLB, CSTR Fmt,...)
Definition: UserUtil.cpp:1303
unsigned long DWORD
Definition: Common.h:414
DWORD GetDLLVersion(CSTR FName)
Definition: ShellUtil.cpp:156
bool CenterWindow(HWND hChild, HWND hParent)
Definition: UserUtil.cpp:563
HICON WINAPI LoadSmallIcon(HINSTANCE hInst, CSTR Id)
Definition: UserUtil.cpp:628
#define MB_USERICON
Definition: UserUtil.cpp:304
bool GetWndPos(HWND hWnd, POINT *pPos)
Definition: UserUtil.cpp:537
bool SetMenuItemCheck(HMENU hMenu, UINT Id, bool Check)
Definition: UserUtil.cpp:694
const char * ACSTR
Definition: Common.h:345
#define SB_SetParts(hctl, npart, ppart)
Definition: UtilFunc.h:1535
#define WINHOOKPROC
Definition: Common.h:1109
HIMAGELIST ImageList_CreateMapped(HINSTANCE hInst, UINT Id, LPCOLORMAP Map, UINT nMap, UINT cxImg, UINT Flags, UINT nGrow)
Definition: UserUtil.cpp:1564
#define CSTR
Definition: Common.h:329
#define GlobalDupStr
Definition: UtilFunc.h:506
#define S_BLANK
Definition: Common.h:1235
IPicture *WINAPI LoadPictureFile(CSTR FName)
Definition: UserUtil.cpp:928
unsigned short WORD
Definition: Common.h:413
#define BEGIN_ANONYMOUS
Definition: Common.h:226
#define IF_DEBUG(code)
Definition: Debug.h:236
HWND CreateDialogParamEx(HINSTANCE hInstance, CSTR Template, HWND hParent, DLGPROC DlgProc, LPARAM lParam, LANGID Language)
Definition: UserUtil.cpp:1077
bool GetTrackbarInfo(HWND hCtl, LPSCROLLINFO psi)
Definition: UserUtil.cpp:1519
#define COMBO_LISTCLASS
Definition: UserUtil.cpp:1207
HWND CreateStatusbar(HWND hParent, UINT Id, CSTR Text, UINT Style)
Definition: UserUtil.cpp:1434
bool AddMenuItem(HMENU hMenu, UINT Index, CSTR Text, WORD cmdId, WORD State, PVOID Data, HBITMAP Image)
Definition: UserUtil.cpp:767
HWND SetParentWnd(HWND wnd, HWND newParent)
Definition: UserUtil.cpp:1167
bool ResizeWnd(HWND hwnd, int W, int H, bool repaint)
Definition: UserUtil.cpp:1159
HWND CreateToolbar(HWND hParent, UINT Id, UINT x, UINT y, UINT w, UINT h, UINT cxBtn, UINT cyBtn, HIMAGELIST hImages, LPTBBUTTON Buttons, UINT nButtons, DWORD Style, DWORD ExStyle)
Definition: UserUtil.cpp:1604
RECT MkRect(LONG L, LONG T, LONG R, LONG B)
Definition: UtilFunc.cpp:46
#define DP_DEBUG
Definition: Debug.h:85
long WINAPI HiMetricToPix(long hiMetric)
Definition: UserUtil.cpp:958
CSTR newStr(CSTR Src)
Definition: StrFunc.cpp:167
wchar_t * WSTR
Definition: Common.h:366
UINT EnumerateMenuItems(HMENU hMenu, PFnMenuItemAction Action, PVOID Ctx)
Definition: UserUtil.cpp:806
bool WINAPI PaintPictureEx(IPicture *pPic, HDC hdc, long x, long y, long cx, long cy, long imx, long imy, long imw, long imh, PRECT prMeta)
Definition: UserUtil.cpp:999
#define TSTR
Definition: Common.h:328
unsigned char * PBYTE
Definition: Common.h:412
void SetWindowDouble(HWND hCtl, int Index, double Value)
Definition: UserUtil.cpp:191
bool GetWndSize(HWND hWnd, SIZE *pSize)
Definition: UserUtil.cpp:523
bool GetRequiredWindowSize(HWND hWnd, IN const PSIZE pClient, OUT PSIZE pWindow)
Definition: UserUtil.cpp:1094
char * ASTR
Definition: Common.h:344
bool EnableChildWnd(HWND Owner, UINT Id, bool Enable)
Definition: UserUtil.cpp:608
#define _MAX_DBGMSG_
Definition: UserUtil.cpp:257
#define dimof(x)
Definition: Common.h:949
bool ButtonChecked(HWND hBtn)
Definition: UserUtil.cpp:1282
#define GWL(hwnd, Item)
Definition: UtilFunc.h:926
#define GWLP(hwnd, Item)
Definition: UtilFunc.h:927
bool IsWndClass(HWND hWnd, CSTR clsName)
Definition: UserUtil.cpp:1210
bool RedrawWndRgn(HWND hwnd, HRGN hrgn, UINT flags)
Definition: UserUtil.cpp:1144
TSTR newStrBuf(WORD nChar)
Definition: StrFunc.cpp:183
INT_PTR DialogBoxParamEx(HINSTANCE hInstance, CSTR Template, HWND hParent, DLGPROC DlgProc, LPARAM lParam, LANGID Language)
Definition: UserUtil.cpp:1061
double GetWndReal(HWND hCtl)
Definition: UserUtil.cpp:1243
bool __cdecl SetCaption(HWND hwnd, CSTR fmt,...)
Definition: UserUtil.cpp:284
#define TRACE(_lvl,...)
Definition: Debug.h:216
bool RedrawWndRect(HWND hwnd, PRECT prect, UINT flags)
Definition: UserUtil.cpp:1139
void WINAPI PaintPicture(IPicture *pPic, HDC hdc, int x, int y, int cx, int cy)
Definition: UserUtil.cpp:977
LPRECT AbsToRelRect(LPRECT pRect)
Definition: UtilFunc.cpp:98
bool SetWndReal(HWND hCtl, double Value, BYTE nDeci, CSTR Suffix)
Definition: UserUtil.cpp:1254
PVOID WINAPI LoadCustomResource(HMODULE hModule, CSTR Id, CSTR Type, UINT *pSize)
Definition: UserUtil.cpp:840
float f
Definition: UserUtil.cpp:166
LPMENUITEMINFO GetMenuItemByName(HMENU hMenu, CSTR Name)
Definition: UserUtil.cpp:650
PINT_PTR pResult
Definition: UserUtil.cpp:320
HANDLE __cdecl AsyncMsgBoxEx(HWND Owner, UINT Flags, CSTR Title, HINSTANCE hInst, CSTR IconId, DWORD LangId, DWORD_PTR HelpId, MSGBOXCALLBACK Callback, PINT_PTR pResult, CSTR TextFmt,...)
Definition: UserUtil.cpp:455
HWND GetMDIClient(HWND hMdiFrame)
Definition: UserUtil.cpp:1269
const wchar_t * WCSTR
Definition: Common.h:367
CSTR DupClipboardString()
Definition: UserUtil.cpp:123
long i
Definition: UserUtil.cpp:165
long WINAPI PixToHiMetric(long Pix)
Definition: UserUtil.cpp:965
HWND CreateWindowIndirect(LPCREATESTRUCT pc)
Definition: UserUtil.cpp:1050
HMODULE GetOrLoadModule(CSTR modName)
Definition: KernelUtil.cpp:376
#define PACKVERSION(maj, min)
Definition: UtilFunc.h:236
#define THREADPROC
Definition: Common.h:1114
int GetMenuItemIdByName(HMENU hMenu, CSTR Name)
Definition: UserUtil.cpp:673
#define TRACE_IF(cond,...)
Definition: Debug.h:227
bool __cdecl SetStatusWidths(HWND hStat, UINT nParts, int *Width)
Definition: UserUtil.cpp:1398
#define MDI_CLIENTCLASS
Definition: UtilFunc.h:1423
BOOL(WINAPI *SysImgList::Shell_GetImageLists)(HIMAGELIST *pimlLarge
const LPCTSTR CCSTR
Definition: Common.h:335
double GetClassDouble(HWND hCtl, int Index)
Definition: UserUtil.cpp:241
#define GetWndStyle(hwnd)
Definition: UtilFunc.h:1121
void WINAPI GetScreenLPI(PPOINT pLpi)
Definition: GdiUtil.cpp:141
ASTR GlobalDupStrA(ACSTR Str, bool isMz=false)
Definition: KernelUtil.cpp:119
long i[2]
Definition: UserUtil.cpp:170
UINT EnumerateClipFormats(HWND hCBOwner, PFClipFmtAction Action, PVOID UserData)
Definition: UserUtil.cpp:55
#define COMBO_EDITCLASS
Definition: UserUtil.cpp:1208
CSTR SysErrorMsg(DWORD Err=0, TSTR Buf=NULL, UINT Length=0)
Definition: Debug.cpp:39
#define SPACE
Definition: Common.h:1219
UINT DispatchMessagesFor(HWND hWnd)
Definition: UserUtil.cpp:17
#define SB_SetText(hctl, part, text)
Definition: UtilFunc.h:1536
int __cdecl AddComboString(HWND hCB, CSTR Fmt,...)
Definition: UserUtil.cpp:1328
HWND GetChildWndWithId(HWND hParent, UINT ChildId)
Definition: UserUtil.cpp:617
signed __int64 INT64
Definition: Common.h:401
bool OpenEmptyClipboard(HWND hWnd)
Definition: UserUtil.cpp:48
WORD RebarBandInfoSize()
Definition: UserUtil.cpp:1671
SIZE MkSize(LONG cx, LONG cy)
Definition: UtilFunc.cpp:36
PVOID WINAPI LoadCustomResourceEx(HMODULE hModule, CSTR Id, CSTR Type, LANGID Language, UINT *pSize)
Definition: UserUtil.cpp:851
bool PutClipboardStringW(HWND hCBOwner, WCSTR Text)
Definition: UserUtil.cpp:117
BOOL GetWindowMinimizeRect(HWND hTrayApp, RECT *pRect)
Definition: UserUtil.cpp:549
PVOID DupClipboardData(UINT clipFmt, PUINT pSize)
Definition: UserUtil.cpp:139
PVOID GetMenuItemData(HMENU hMenu, UINT Id)
Definition: UserUtil.cpp:681
SECURITY_ATTRIBUTES DefSec
Definition: Common.cpp:20
HWND GetComboEditor(HWND hCombo)
Definition: UserUtil.cpp:1218
float GetClassFloat(HWND hCtl, int Index)
Definition: UserUtil.cpp:222
bool __forceinline bool_cast(BOOL B52)
Definition: Common.h:767
#define DP_ERROR
Definition: Debug.h:82
#define BITS_SET(bits, x)
Definition: Common.h:1016
double GetWindowDouble(HWND hCtl, int Index)
Definition: UserUtil.cpp:203
bool GetWindowClientSize(HWND hWnd, IN const PSIZE pWindow, OUT PSIZE pClient)
Definition: UserUtil.cpp:1109
float GetWindowFloat(HWND hCtl, int Index)
Definition: UserUtil.cpp:184
bool RefreshWnd(HWND hwnd)
Definition: UserUtil.cpp:1126
bool(__stdcall * PFLvItemAction)(HWND hList, LPLVITEM pItem, PVOID pCtx)
Definition: UtilFunc.h:1565
HWND CreateStdToolbar(HWND hParent, UINT Id, UINT x, UINT y, UINT w, UINT h, UINT imgType, LPTBBUTTON Buttons, UINT nButtons, DWORD Style, DWORD ExStyle)
Definition: UserUtil.cpp:1640
MsgBoxParams * PMsgBoxParams
Definition: UserUtil.cpp:326
Debug and error handling support.
HINSTANCE hInstance
Definition: Common.cpp:10
int __cdecl MsgBox(HWND owner, UINT type, CSTR cap, CSTR msg,...)
Definition: UserUtil.cpp:271
void GetChildWndRect(HWND hCtl, RECT *R)
Definition: UserUtil.cpp:602
double d
Definition: UserUtil.cpp:172
bool MoveWnd(HWND hwnd, int X, int Y, bool repaint)
Definition: UserUtil.cpp:1151
bool SetDlgItemReal(HWND hDlg, UINT Id, double Value, BYTE nDeci, CSTR Suffix)
Definition: UserUtil.cpp:1262
UINT GetWndHeight(HWND hWnd)
Definition: UserUtil.cpp:507
#define SetWndStyle(hwnd, style)
Definition: UtilFunc.h:1122
bool PutClipHandle(HWND hCBOwner, HANDLE hClip, UINT clipFmt)
Definition: UserUtil.cpp:73
PDirEntry PScanDirCtx pCtx
Definition: FileDir.cpp:51
IPicture *WINAPI LoadPictureResource(HMODULE hMod, CSTR Id, CSTR Type)
Definition: UserUtil.cpp:900
int AddComboItem(HWND hCB, CSTR Text, LPARAM Data)
Definition: UserUtil.cpp:1340
Common include; Added types, small "ubiquitous" utilities, et c.
#define MB_SYSICONMASK
Definition: UserUtil.cpp:301
void SetClassFloat(HWND hCtl, int Index, float Value)
Definition: UserUtil.cpp:215
bool(__stdcall * PFnMenuItemAction)(HMENU hMenu, MENUITEMINFO *pInfo, PVOID Ctx)
Definition: UtilFunc.h:1388
void SetClassDouble(HWND hCtl, int Index, double Value)
Definition: UserUtil.cpp:229
#define END_ANONYMOUS
Definition: Common.h:227
#define _F(s)
Definition: Debug.h:49
bool __cdecl SetStatusText(HWND hStat, UINT Part, CSTR Fmt,...)
Definition: UserUtil.cpp:1422
WSTR GlobalDupStrW(WCSTR Str, bool isMz=false)
Definition: KernelUtil.cpp:142
bool CheckButtonCtrl(HWND hDlg, UINT Id, bool Check)
Definition: UserUtil.cpp:1296
bool(__stdcall * PFClipFmtAction)(UINT FmtTag, PVOID UserData)
Definition: UtilFunc.h:976
POINT MkPoint(LONG x, LONG y)
Definition: UtilFunc.cpp:26
#define MIIM_ALL
Definition: UtilFunc.h:1326
LPRECT AbsToDimRect(LPRECT pRect)
Definition: UtilFunc.cpp:86
CSTR deleteStr(CSTR Dup)
Definition: StrFunc.cpp:191
bool ButtonCtrlChecked(HWND hDlg, UINT Id)
Definition: UserUtil.cpp:1286
#define DP_VERBOSE
Definition: Debug.h:86
HWND hMainWnd
Definition: Common.cpp:12
HANDLE __cdecl AsyncMsgBox(UINT Flags, PINT_PTR pResult, CSTR Title, CSTR Fmt,...)
Definition: UserUtil.cpp:430
HMENU AddSubMenu(HMENU hMenu, UINT Index, CSTR Text, WORD Id, WORD State, PVOID Data, HBITMAP Image)
Definition: UserUtil.cpp:718
bool __cdecl SetStatusParts(HWND hStat, UINT nParts,...)
Definition: UserUtil.cpp:1377
HMENU LoadMenuEx(HMODULE hModule, CSTR Id, LANGID Language)
Definition: UserUtil.cpp:639
HANDLE GetClipHandle(UINT clipFmt)
Definition: UserUtil.cpp:85
CSTR GetWndClassName(HWND hWnd)
Definition: UserUtil.cpp:1232
UINT ListView_ForEach(HWND hLv, PFLvItemAction Action, PVOID pCtx)
Definition: UserUtil.cpp:1461
HWND GetComboList(HWND hCombo)
Definition: UserUtil.cpp:1225
int AddListItem(HWND hLB, CSTR Text, LPARAM Data)
Definition: UserUtil.cpp:1315
#define DP_WARNING
Definition: Debug.h:83
bool TreeView_GetItemText(HWND hTree, HTREEITEM hItem, TSTR Buf, UINT bufLen)
Definition: UserUtil.cpp:1493
UINT GetWndWidth(HWND hWnd)
Definition: UserUtil.cpp:515
unsigned char BYTE
Definition: Common.h:412
bool SetTrackbarInfo(HWND hCtl, LPSCROLLINFO psi, bool Redraw)
Definition: UserUtil.cpp:1543
bool __forceinline IsString(CSTR Str)
Definition: StrFunc.h:84
MsgBoxParams(CSTR title, WORD maxText, UINT flags)
Definition: UserUtil.cpp:328
bool CheckButton(HWND hBtn, bool Check)
Definition: UserUtil.cpp:1291
END_ANONYMOUS void SetWindowFloat(HWND hCtl, int Index, float Value)
Definition: UserUtil.cpp:177
bool PutClipboardStringA(HWND hCBOwner, ACSTR Text)
Definition: UserUtil.cpp:111
double GetDlgItemReal(HWND hDlg, UINT Id)
Definition: UserUtil.cpp:1249
bool RedrawWnd(HWND hwnd, UINT flags)
Definition: UserUtil.cpp:1134
INT64 i64
Definition: UserUtil.cpp:171