1 /*
2 * Copyright 2003, 2004, 2005 Martin Fuchs
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19
20 //
21 // Explorer clone
22 //
23 // utility.h
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27
28 // standard windows headers
29 #define WIN32_LEAN_AND_MEAN
30 #define WIN32_EXTRA_LEAN
31 #define WIN32_NO_STATUS
32 #define _INC_WINDOWS
33 #define COM_NO_WINDOWS_H
34 #include <stdarg.h>
35 #include <windef.h>
36 #include <winbase.h>
37 #include <winuser.h>
38
39 //#include <undocuser.h>
40
41 // Unicode support
42 #if defined(UNICODE) && !defined(_UNICODE)
43 #define _UNICODE
44 #endif
45 #include <tchar.h>
46
47 #include <windowsx.h> // for SelectBrush(), ListBox_SetSel(), SubclassWindow(), ...
48 #include <commctrl.h>
49
50 #include <objbase.h>
51 //#include <oleauto.h> // for VARIANT
52
53 //#include <malloc.h> // for alloca()
54 #include <assert.h>
55 //#include <stdlib.h> // for _MAX_DIR, ...
56 #include <stdio.h> // for sprintf()
57 //#include <time.h>
58
59 #ifdef __cplusplus
60
61 #ifdef _MSC_VER
62 #pragma warning(disable: 4786) // disable warnings about too long debug information symbols
63 #endif
64
65 // STL headers for strings and streams
66 #include <string>
67 #include <iostream>
68 using namespace std;
69
70 #endif /* __cplusplus */
71
72 #ifndef _MAX_PATH
73 #define _MAX_DRIVE 3
74 #define _MAX_FNAME 256
75 #define _MAX_DIR _MAX_FNAME
76 #define _MAX_EXT _MAX_FNAME
77 #define _MAX_PATH 260
78 #endif
79
80 #define W_VER_NT 0 // constant for HIWORD(GetVersion())>>14
81
82
83 #ifdef __cplusplus
84 extern "C" {
85 #endif
86
87
88 #define for if (0) {} else for
89
90 #ifdef _countof
91 #define COUNTOF _countof
92 #else
93 #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
94 #endif
95
96
97 #define BUFFER_LEN 2048
98
99
100 extern void _log_(LPCTSTR txt);
101
102 #define LOG(txt) _log_(txt)
103
104
105 #ifdef _MSC_VER
106 #define LONGLONGARG TEXT("I64")
107 #else
108 #define LONGLONGARG TEXT("L")
109 #endif
110
111
112 #ifndef _tcsrchr
113 #ifdef UNICODE
114 #define _tcsrchr wcsrchr
115 #else
116 #define _tcsrchr strrchr
117 #endif
118 #endif
119
120 #ifndef _stprintf
121 #ifdef UNICODE
122 #define _stprintf wcsprintf
123 #else
124 #define _stprintf sprintf
125 #endif
126 #endif
127
128 #define U2A(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, -1, d, l, NULL, NULL)
129 #define U2nA(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, l, d, l, NULL, NULL)
130 #define A2U(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, -1, d, l)
131 #define A2nU(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, l, d, l)
132
133
134 #ifdef __WINE__
135 #ifdef UNICODE
136 extern void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext);
137 #else
138 extern void _splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext);
139 #endif
140 #define _tcsnicmp strncasecmp
141 #define _tcsicoll strcasecmp
142 #endif
143
144 #ifndef FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
145 #define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
146 #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
147 #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
148 #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
149 #endif
150
151
152 #define SetDlgCtrlID(hwnd, id) SetWindowLongPtr(hwnd, GWL_ID, id)
153 #define SetWindowStyle(hwnd, val) (DWORD)SetWindowLongPtr(hwnd, GWL_STYLE, val)
154 #define SetWindowExStyle(h, val) (DWORD)SetWindowLongPtr(hwnd, GWL_EXSTYLE, val)
155 #define Window_SetIcon(hwnd, type, hicon) (HICON)SendMessage(hwnd, WM_SETICON, type, (LPARAM)(hicon))
156
157
158 // center window in respect to its parent window
159 extern void CenterWindow(HWND hwnd);
160
161 // move window into visibility
162 extern void MoveVisible(HWND hwnd);
163
164 // display error message
165 extern void display_error(HWND hwnd, DWORD error);
166
167 // convert time_t to WIN32 FILETIME
168 extern BOOL time_to_filetime(const time_t* t, FILETIME* ftime);
169
170 // search for windows of a specific classname
171 extern int find_window_class(LPCTSTR classname);
172
173 // create a directory with all missing parent directories
174 BOOL RecursiveCreateDirectory(LPCTSTR path_in);
175
176 // read DWORD value from registry
177 DWORD RegGetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD def);
178
179 // write DWORD value to registry
180 BOOL RegSetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD value);
181
182 // test for existing directory
183 BOOL exists_path(LPCTSTR path);
184
185
186 #ifdef __cplusplus
187 } // extern "C"
188 #endif
189
190
191 // secure CRT functions
192 //@@ _MS_VER: temporarily needed for the ReactOS build environment
193 #if defined(__STDC_WANT_SECURE_LIB__) && defined(_MS_VER) // for VS 2005: _MSC_VER>=1400
194
195 #define _stprintf_s1 _stprintf_s
196 #define _stprintf_s2 _stprintf_s
197
198 #else // __STDC_WANT_SECURE_LIB__
199
200 #define strcpy_s(d, l, s) strcpy(d, s)
201 #define wcscpy_s(d, l, s) wcscpy(d, s)
202 #define wcsncpy_s(d, l, s, n) wcsncpy(d, s, n)
203
204 #if defined(_tcscpy) && !defined(_tcscpy_s)
205 #define _tcscpy_s(d, l, s) _tcscpy(d, s)
206 #endif
207
208 #if defined(_tsplitpath) && !defined(_tsplitpath_s)
209 #define _tsplitpath_s(f, d,dl, p,pl, n,nl, e,el) _tsplitpath(f, d, p, n, e)
210 #else
211 #define _wsplitpath_s(f, d,dl, p,pl, n,nl, e,el) _wsplitpath(f, d, p, n, e)
212 #define _splitpath_s(f, d,dl, p,pl, n,nl, e,el) _splitpath(f, d, p, n, e)
213 #endif
214
215 #define _stprintf_s1(b, l, f, p1) _stprintf(b, f, p1)
216 #define _stprintf_s2(b, l, f, p1,p2) _stprintf(b, f, p1,p2)
217
218 #endif // __STDC_WANT_SECURE_LIB__
219
220
221 #ifdef __cplusplus
222
223 // containers
224 #include <map>
225 #include <set>
226 #include <list>
227 #include <stack>
228 #include <vector>
229
230
231 /* not necessary with correct include file order for comdef.h ("<MS PSDK>\include" path first) */
232 #if _MSC_VER>=1300 // VS.Net
233 #define _NO_COMUTIL
234 #endif
235
236
237 #if defined(_MSC_VER) && !defined(_NO_COMUTIL)
238
239 // COM utility headers
240 #include <comdef.h>
241 using namespace _com_util;
242
243 #endif // _MSC_VER && !_NO_COMUTIL
244
245
246 // launch a program or document file
247 extern BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow=SW_SHOWNORMAL, LPCTSTR parameters=NULL);
248 #ifdef UNICODE
249 extern BOOL launch_fileA(HWND hwnd, LPSTR cmd, UINT nCmdShow=SW_SHOWNORMAL, LPCSTR parameters=NULL);
250 #else
251 #define launch_fileA launch_file
252 #endif
253
254 // call an DLL export like rundll32
255 extern BOOL RunDLL(HWND hwnd, LPCTSTR dllname, LPCSTR procname, LPCTSTR cmdline, UINT nCmdShow);
256
257 // launch control panel applet
258 extern BOOL launch_cpanel(HWND hwnd, LPCTSTR applet);
259
260
261 /// initialization of windows common controls
262 struct CommonControlInit
263 {
264 CommonControlInit(DWORD flags=ICC_LISTVIEW_CLASSES|ICC_TREEVIEW_CLASSES|ICC_BAR_CLASSES|ICC_PROGRESS_CLASS|ICC_COOL_CLASSES)
265 {
266 INITCOMMONCONTROLSEX icc = {sizeof(INITCOMMONCONTROLSEX), flags};
267
268 InitCommonControlsEx(&icc);
269 }
270 };
271
272
273 /// wait cursor
274
275 struct WaitCursor ///@todo integrate with WM_SETCURSOR to enable multithreaded background tasks as program launching
276 {
WaitCursorWaitCursor277 WaitCursor()
278 {
279 _old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
280 }
281
~WaitCursorWaitCursor282 ~WaitCursor()
283 {
284 SetCursor(_old_cursor);
285 }
286
287 protected:
288 HCURSOR _old_cursor;
289 };
290
291
292 /// base of all structures storing a window handle
293 struct WindowHandle
294 {
295 WindowHandle(HWND hwnd=0)
_hwndWindowHandle296 : _hwnd(hwnd) {}
297
HWNDWindowHandle298 operator HWND() const {return _hwnd;}
299 HWND* operator&() {return &_hwnd;}
300
301 protected:
302 HWND _hwnd;
303 };
304
305
306 /// locally hide a window
307 struct HiddenWindow : public WindowHandle
308 {
HiddenWindowHiddenWindow309 HiddenWindow(HWND hwnd)
310 : WindowHandle(IsWindowVisible(hwnd)? hwnd: 0)
311 {
312 if (_hwnd)
313 SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
314 }
315
~HiddenWindowHiddenWindow316 ~HiddenWindow()
317 {
318 if (_hwnd)
319 SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
320 }
321 };
322
323
324 /// critical section wrapper
325
326 struct CritSect : public CRITICAL_SECTION
327 {
CritSectCritSect328 CritSect()
329 {
330 InitializeCriticalSection(this);
331 }
332
~CritSectCritSect333 ~CritSect()
334 {
335 DeleteCriticalSection(this);
336 }
337 };
338
339
340 /// Lock protects a code section utilizing a critical section
341
342 struct Lock
343 {
LockLock344 Lock(CritSect& crit_sect)
345 : _crit_sect(crit_sect)
346 {
347 EnterCriticalSection(&crit_sect);
348 }
349
~LockLock350 ~Lock()
351 {
352 LeaveCriticalSection(&_crit_sect);
353 }
354
355 protected:
356 CritSect& _crit_sect;
357 };
358
359
360 /// Thread base class
361
362 struct Thread
363 {
ThreadThread364 Thread()
365 : _alive(false),
366 _destroy(false)
367 {
368 _hThread = INVALID_HANDLE_VALUE;
369 _evtFinish = CreateEvent(NULL, TRUE, FALSE, NULL);
370 }
371
~ThreadThread372 virtual ~Thread()
373 {
374 Stop();
375
376 CloseHandle(_evtFinish);
377 CloseHandle(_hThread);
378
379 if (_destroy)
380 delete this;
381 }
382
StartThread383 void Start()
384 {
385 if (!_alive) {
386 _alive = true;
387 _hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
388 }
389 }
390
StopThread391 void Stop()
392 {
393 SetEvent(_evtFinish);
394
395 if (_alive) {
396 {
397 Lock lock(_crit_sect);
398 _alive = false;
399 }
400
401 // wait for finishing
402 WaitForSingleObject(_hThread, INFINITE);
403 }
404 }
405
406 virtual int Run() = 0;
407
is_aliveThread408 bool is_alive() const {return _alive;}
409
410 CritSect _crit_sect;
411
412 protected:
413 static DWORD WINAPI ThreadProc(void* para);
414
415 HANDLE _hThread;
416 HANDLE _evtFinish;
417 bool _alive;
418 bool _destroy;
419 };
420
421
422 // window utilities
423
424 /// ClientRect retreives the client area rectangle of a window.
425 struct ClientRect : public RECT
426 {
ClientRectClientRect427 ClientRect(HWND hwnd)
428 {
429 GetClientRect(hwnd, this);
430 }
431
LPRECTClientRect432 operator LPRECT() {return this;}
433
posClientRect434 POINT& pos() {return *(LPPOINT)this;}
435 };
436
437 /// ClientRect retreives the window rectangle of a window.
438 struct WindowRect : public RECT
439 {
WindowRectWindowRect440 WindowRect(HWND hwnd)
441 {
442 GetWindowRect(hwnd, this);
443 }
444
LPRECTWindowRect445 operator LPRECT() {return this;}
446
posWindowRect447 POINT& pos() {return *(LPPOINT)this;}
448 };
449
450 /// PointL encapsulates the POINT structure into a C++ object.
451 struct Point : public POINT
452 {
PointPoint453 Point(LONG x_, LONG y_)
454 {
455 x = x_;
456 y = y_;
457 }
458
459 // constructor for being used in processing WM_MOUSEMOVE, WM_LBUTTONDOWN, ... messages
PointPoint460 Point(LPARAM lparam)
461 {
462 x = GET_X_LPARAM(lparam);
463 y = GET_Y_LPARAM(lparam);
464 }
465
LPPOINTPoint466 operator LPPOINT() {return this;}
467 };
468
469
470 /// transform coordinates in a RECT from client to screen coordiantes
ClientToScreen(HWND hwnd,RECT * prect)471 inline void ClientToScreen(HWND hwnd, RECT* prect)
472 {::ClientToScreen(hwnd,(LPPOINT)&prect->left); ::ClientToScreen(hwnd,(LPPOINT)&prect->right);}
473
474 /// transform coordinates in a RECT from screen to client coordiantes
ScreenToClient(HWND hwnd,RECT * prect)475 inline void ScreenToClient(HWND hwnd, RECT* prect)
476 {::ScreenToClient(hwnd,(LPPOINT)&prect->left); ::ScreenToClient(hwnd,(LPPOINT)&prect->right);}
477
478
479 /// structure containing information about full screen display of the frame window
480 struct FullScreenParameters
481 {
FullScreenParametersFullScreenParameters482 FullScreenParameters()
483 : _mode(FALSE)
484 {
485 }
486
487 BOOL _mode;
488 RECT _orgPos;
489 BOOL _wasZoomed;
490 };
491
492
493 // drawing utilities
494
495 /// PaintCanvas is a encapsulation of device contexts managed by BeginPaint()/EndPaint().
496 struct PaintCanvas : public PAINTSTRUCT
497 {
PaintCanvasPaintCanvas498 PaintCanvas(HWND hwnd)
499 : _hwnd(hwnd)
500 {
501 BeginPaint(hwnd, this);
502 }
503
~PaintCanvasPaintCanvas504 ~PaintCanvas()
505 {
506 EndPaint(_hwnd, this);
507 }
508
HDCPaintCanvas509 operator HDC() const {return hdc;}
510
511 protected:
512 HWND _hwnd;
513 };
514
515 /// Canvas is a encapsulation of device contexts.
516 struct Canvas
517 {
CanvasCanvas518 Canvas(HDC hdc) : _hdc(hdc) {}
519
HDCCanvas520 operator HDC() {return _hdc;}
521
522 protected:
523 HDC _hdc;
524 };
525
526 /// WindowCanvas is a encapsulation of client area device contexts.
527 struct WindowCanvas : public Canvas
528 {
WindowCanvasWindowCanvas529 WindowCanvas(HWND hwnd)
530 : Canvas(GetDC(hwnd)), _hwnd(hwnd) {}
531
~WindowCanvasWindowCanvas532 ~WindowCanvas() {ReleaseDC(_hwnd, _hdc);}
533
534 protected:
535 HWND _hwnd;
536 };
537
538
539 // double buffering classes
540
541 /// Memory Canvas creates and destroys memory devoce contexts.
542 struct MemCanvas : public Canvas
543 {
544 MemCanvas(HDC hdc=0)
CanvasMemCanvas545 : Canvas(CreateCompatibleDC(hdc)) {assert(_hdc);}
546
~MemCanvasMemCanvas547 ~MemCanvas() {DeleteDC(_hdc);}
548 };
549
550 /// SelectedBitmap is used to localy select bitmaps into device contexts.
551 struct SelectedBitmap
552 {
SelectedBitmapSelectedBitmap553 SelectedBitmap(HDC hdc, HBITMAP hbmp)
554 : _hdc(hdc), _old_hbmp(SelectBitmap(hdc, hbmp)) {}
555
~SelectedBitmapSelectedBitmap556 ~SelectedBitmap() {DeleteObject(SelectBitmap(_hdc, _old_hbmp));}
557
558 protected:
559 HDC _hdc;
560 HBITMAP _old_hbmp;
561 };
562
563 /// BufferCanvas manages offscreen bitmaps selected into memory device contexts.
564 struct BufferCanvas : public MemCanvas
565 {
BufferCanvasBufferCanvas566 BufferCanvas(HDC hdc, int x, int y, int w, int h)
567 : MemCanvas(hdc), _hdctarg(hdc),
568 _x(x), _y(y), _w(w), _h(h),
569 _bmp(_hdc, CreateCompatibleBitmap(hdc, w, h)) {}
570
BufferCanvasBufferCanvas571 BufferCanvas(HDC hdc, const RECT& rect)
572 : MemCanvas(hdc), _hdctarg(hdc),
573 _x(rect.left), _y(rect.top), _w(rect.right-rect.left), _h(rect.bottom-rect.top),
574 _bmp(_hdc, CreateCompatibleBitmap(hdc, _w, _h)) {}
575
576 protected:
577 HDC _hdctarg;
578 int _x, _y, _w, _h;
579 SelectedBitmap _bmp;
580 };
581
582 /// BufferedCanvas enables double buffering for a device context.
583 struct BufferedCanvas : public BufferCanvas
584 {
585 BufferedCanvas(HDC hdc, int x, int y, int w, int h, DWORD mode=SRCCOPY)
BufferCanvasBufferedCanvas586 : BufferCanvas(hdc, x, y, w, h), _mode(mode) {}
587
588 BufferedCanvas(HDC hdc, const RECT& rect, DWORD mode=SRCCOPY)
BufferCanvasBufferedCanvas589 : BufferCanvas(hdc, rect), _mode(mode) {}
590
~BufferedCanvasBufferedCanvas591 ~BufferedCanvas() {BitBlt(_hdctarg, _x, _y, _w, _h, _hdc, 0, 0, _mode);}
592
593 DWORD _mode;
594 };
595
596 /// BufferedPaintCanvas extends PaintCanvas for double buffering.
597 struct BufferedPaintCanvas : public PaintCanvas, public BufferedCanvas
598 {
BufferedPaintCanvasBufferedPaintCanvas599 BufferedPaintCanvas(HWND hwnd)
600 : PaintCanvas(hwnd),
601 BufferedCanvas(PAINTSTRUCT::hdc, 0, 0, rcPaint.right, rcPaint.bottom)
602 {
603 }
604
HDCBufferedPaintCanvas605 operator HDC() {return BufferedCanvas::_hdc;}
606 };
607
608
609 /// TextColor locally selects a text color for drawing.
610 struct TextColor
611 {
TextColorTextColor612 TextColor(HDC hdc, COLORREF color)
613 : _hdc(hdc), _old_color(SetTextColor(hdc, color)) {}
614
~TextColorTextColor615 ~TextColor() {SetTextColor(_hdc, _old_color);}
616
617 protected:
618 HDC _hdc;
619 COLORREF _old_color;
620 };
621
622 /// BkMode locally sets the background mode for drawing.
623 struct BkMode
624 {
BkModeBkMode625 BkMode(HDC hdc, int bkmode)
626 : _hdc(hdc), _old_bkmode(SetBkMode(hdc, bkmode)) {}
627
~BkModeBkMode628 ~BkMode() {SetBkMode(_hdc, _old_bkmode);}
629
630 protected:
631 HDC _hdc;
632 COLORREF _old_bkmode;
633 };
634
635 /// FontSelection locally selects a font for drawing.
636 struct FontSelection
637 {
FontSelectionFontSelection638 FontSelection(HDC hdc, HFONT hFont)
639 : _hdc(hdc), _old_hFont(SelectFont(hdc, hFont)) {}
640
~FontSelectionFontSelection641 ~FontSelection() {SelectFont(_hdc, _old_hFont);}
642
643 protected:
644 HDC _hdc;
645 HFONT _old_hFont;
646 };
647
648 /// BitmapSelection locally selects a bitmap into a device context.
649 struct BitmapSelection
650 {
BitmapSelectionBitmapSelection651 BitmapSelection(HDC hdc, HBITMAP hBmp)
652 : _hdc(hdc), _old_hBmp(SelectBitmap(hdc, hBmp)) {}
653
~BitmapSelectionBitmapSelection654 ~BitmapSelection() {SelectBitmap(_hdc, _old_hBmp);}
655
656 protected:
657 HDC _hdc;
658 HBITMAP _old_hBmp;
659 };
660
661 /// BrushSelection locally selects a brush into a device context.
662 struct BrushSelection
663 {
BrushSelectionBrushSelection664 BrushSelection(HDC hdc, HBRUSH hBrush)
665 : _hdc(hdc), _old_hBrush(SelectBrush(hdc, hBrush)) {}
666
~BrushSelectionBrushSelection667 ~BrushSelection() {SelectBrush(_hdc, _old_hBrush);}
668
669 protected:
670 HDC _hdc;
671 HBRUSH _old_hBrush;
672 };
673
674
675 /// Popup Menus
676 struct PopupMenu
677 {
PopupMenuPopupMenu678 PopupMenu()
679 : _hmenu(CreatePopupMenu())
680 {
681 }
682
~PopupMenuPopupMenu683 ~PopupMenu()
684 {
685 DestroyMenu(_hmenu);
686 }
687
688 PopupMenu(UINT nid);
689
HMENUPopupMenu690 operator HMENU() {return _hmenu;}
691
692 void Append(UINT id, LPCTSTR str, UINT flags=MF_STRING)
693 {
694 AppendMenu(_hmenu, flags, id, str);
695 }
696
697 int TrackPopupMenu(HWND hwnd, const POINT& pt, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON, LPTPMPARAMS tpm=NULL) {
698 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, tpm);
699 }
700
701 int PopupContextMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
702 POINT pt;
703 pt.x = pos.x;
704 pt.y = pos.y;
705 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
706 }
707
708 int TrackPopupMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
709 POINT pt;
710 pt.x = pos.x;
711 pt.y = pos.y;
712 ClientToScreen(hwnd, &pt);
713 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
714 }
715
716 int TrackPopupMenuAtCursor(HWND hwnd, UINT flags=TPM_LEFTBUTTON) {
717 POINT pt; GetCursorPos(&pt);
718 return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
719 }
720
721 int TrackPopupMenuAtPos(HWND hwnd, DWORD pos, UINT flags=TPM_LEFTBUTTON) {
722 return TrackPopupMenuEx(_hmenu, flags, GET_X_LPARAM(pos), GET_Y_LPARAM(pos), hwnd, NULL);
723 }
724
725 protected:
726 HMENU _hmenu;
727 };
728
729
730 struct Variant : public VARIANT
731 {
VariantVariant732 Variant() {VariantInit(this);}
733 Variant(const VARIANT& var);
734 Variant(const VARIANT* var);
735 ~Variant();
736
737 operator long() const;
738 operator bool() const;
739 operator VARIANT_BOOL() const;
740 operator IDispatch*() const;
741 };
742
743
744 struct BStr
745 {
BStrBStr746 BStr()
747 {
748 _p = NULL;
749 }
750
BStrBStr751 BStr(const BSTR s)
752 {
753 _p = SysAllocString(s);
754 }
755
BStrBStr756 BStr(LPCSTR s)
757 {
758 WCHAR b[BUFFER_LEN];
759
760 if (s)
761 _p = SysAllocStringLen(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1);
762 else
763 _p = NULL;
764 }
765
BStrBStr766 BStr(LPCWSTR s)
767 {
768 _p = SysAllocString(s);
769 }
770
BStrBStr771 BStr(const VARIANT& var)
772 : _p(NULL)
773 {
774 assign(var);
775 }
776
~BStrBStr777 ~BStr()
778 {
779 SysFreeString(_p);
780 }
781
782 void assign(BSTR s);
783 void assign(const VARIANT& var);
784
BSTRBStr785 operator BSTR() const
786 {
787 return _p? _p: (BSTR)L"";
788 }
789
lengthBStr790 int length() const
791 {
792 return _p? wcslen(_p): 0;
793 }
794
795 protected:
796 BSTR _p;
797 };
798
799
800 /// string class for TCHAR strings
801 struct String
802 #ifdef UNICODE
803 : public wstring
804 #else
805 : public string
806 #endif
807 {
808 #ifdef UNICODE
809 typedef wstring super;
810 #else
811 typedef string super;
812 #endif
813
StringString814 String() {}
815
StringString816 String(LPCTSTR s) {if (s) super::assign(s);}
StringString817 String(LPCTSTR s, int l) : super(s, l) {}
818
StringString819 String(const super& other) : super(other) {}
StringString820 String(const String& other) : super(other) {}
821
822 #ifdef UNICODE
StringString823 String(LPCSTR s) {assign(s);}
StringString824 String(LPCSTR s, int l) {assign(s, l);}
StringString825 String(const string& other) {assign(other.c_str());}
826 String& operator=(LPCSTR s) {assign(s); return *this;}
assignString827 void assign(LPCSTR s) {if (s) {TCHAR b[BUFFER_LEN]; super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1);} else erase();}
assignString828 void assign(LPCSTR s, int l) {if (s) {TCHAR b[BUFFER_LEN]; super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, BUFFER_LEN));} else erase();}
assignString829 void assign(const BStr& s) {int l = s.length(); super::assign(s, l);}
830 #else
StringString831 String(LPCWSTR s) {assign(s);}
StringString832 String(LPCWSTR s, int l) {assign(s, l);}
StringString833 String(const wstring& other) {assign(other.c_str());}
834 String& operator=(LPCWSTR s) {assign(s); return *this;}
assignString835 void assign(LPCWSTR s) {if (s) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, -1, b, BUFFER_LEN, 0, 0)-1);} else erase();}
assignString836 void assign(LPCWSTR s, int l) {if (s) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, BUFFER_LEN, 0, 0));} else erase();}
assignString837 void assign(const BStr& s) {int l = s.length(); if (l) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, BUFFER_LEN, 0, 0));} else erase();}
838 #endif
StringString839 String(const BStr& s) {assign(s);}
840 String& operator=(const BStr& s) {assign(s); return *this;}
841
842 String& operator=(LPCTSTR s) {if (s) super::assign(s); else erase(); return *this;}
843 String& operator=(const super& s) {super::assign(s); return *this;}
assignString844 void assign(LPCTSTR s) {super::assign(s);}
assignString845 void assign(LPCTSTR s, int l) {super::assign(s, l);}
846
LPCTSTRString847 operator LPCTSTR() const {return c_str();}
848
849 #ifdef UNICODE
stringString850 operator string() const {char b[BUFFER_LEN]; return string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN, 0, 0)-1);}
851 #else
wstringString852 operator wstring() const {WCHAR b[BUFFER_LEN]; return wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN)-1);}
853 #endif
854
strString855 LPTSTR str() {return (LPTSTR)data();} /// return modifyable character string pointer
856
printfString857 String& printf(LPCTSTR fmt, ...)
858 {
859 va_list l;
860 TCHAR b[BUFFER_LEN];
861
862 va_start(l, fmt);
863 super::assign(b, _vsntprintf(b, COUNTOF(b), fmt, l));
864 va_end(l);
865
866 return *this;
867 }
868
vprintfString869 String& vprintf(LPCTSTR fmt, va_list l)
870 {
871 TCHAR b[BUFFER_LEN];
872
873 super::assign(b, _vsntprintf(b, COUNTOF(b), fmt, l));
874
875 return *this;
876 }
877
appendfString878 String& appendf(LPCTSTR fmt, ...)
879 {
880 va_list l;
881 TCHAR b[BUFFER_LEN];
882
883 va_start(l, fmt);
884 super::append(b, _vsntprintf(b, COUNTOF(b), fmt, l));
885 va_end(l);
886
887 return *this;
888 }
889
vappendfString890 String& vappendf(LPCTSTR fmt, va_list l)
891 {
892 TCHAR b[BUFFER_LEN];
893
894 super::append(b, _vsntprintf(b, COUNTOF(b), fmt, l));
895
896 return *this;
897 }
898
toLowerString899 void toLower()
900 {
901 if (!empty())
902 CharLower(str());
903 }
904 };
905
906 #define _STRING_DEFINED
907
908
909 struct FmtString : public String
910 {
FmtStringFmtString911 FmtString(LPCTSTR fmt, ...)
912 {
913 va_list l;
914
915 va_start(l, fmt);
916 vprintf(fmt, l);
917 va_end(l);
918 }
919 };
920
921
922 #ifdef UNICODE
923
924 struct ANS
925 {
ANSANS926 ANS(LPCWSTR s)
927 {
928 int l = wcslen(s) + 1;
929 _str = (LPSTR) malloc(2*l);
930
931 if (WideCharToMultiByte(CP_ACP, 0, s, -1, _str, 2*l, 0, 0) <= 0)
932 *_str = '\0';
933 }
934
~ANSANS935 ~ANS()
936 {
937 free(_str);
938 }
939
LPCSTRANS940 operator LPCSTR() {return _str;}
941
942 protected:
943 LPSTR _str;
944 };
945
946 #define UNC(x) ((LPCWSTR)(x))
947
948 #else
949
950 #define ANS(x) ((LPCSTR)(x))
951
952 struct UNC
953 {
UNCUNC954 UNC(LPCSTR s)
955 {
956 int l = strlen(s) + 1;
957 _str = (LPWSTR) malloc(2*l);
958
959 if (_str && MultiByteToWideChar(CP_ACP, 0, s, -1, _str, l) <= 0)
960 *_str = '\0';
961 }
962
~UNCUNC963 ~UNC()
964 {
965 free(_str);
966 }
967
LPCWSTRUNC968 operator LPCWSTR() {return _str;}
969
970 protected:
971 LPWSTR _str;
972 };
973
974 #endif
975
976
977 // determine windows version string
978 String get_windows_version_str();
979
980
981 /// link dynamicly to functions by using GetModuleHandle() and GetProcAddress()
982 template<typename FCT> struct DynamicFct
983 {
DynamicFctDynamicFct984 DynamicFct(LPCTSTR moduleName, UINT ordinal)
985 {
986 HMODULE hModule = GetModuleHandle(moduleName);
987
988 _fct = (FCT) GetProcAddress(hModule, (LPCSTR)ordinal);
989 }
990
DynamicFctDynamicFct991 DynamicFct(LPCTSTR moduleName, LPCSTR name)
992 {
993 HMODULE hModule = GetModuleHandle(moduleName);
994
995 _fct = (FCT) GetProcAddress(hModule, name);
996 }
997
998 FCT operator*() const {return _fct;}
999 operator bool() const {return _fct? true: false;}
1000
1001 protected:
1002 FCT _fct;
1003 };
1004
1005
1006 /// link dynamicly to functions by using LoadLibrary() and GetProcAddress()
1007 template<typename FCT> struct DynamicLoadLibFct
1008 {
DynamicLoadLibFctDynamicLoadLibFct1009 DynamicLoadLibFct(LPCTSTR moduleName, UINT ordinal)
1010 {
1011 _hModule = LoadLibrary(moduleName);
1012
1013 _fct = (FCT) GetProcAddress(_hModule, (LPCSTR)ordinal);
1014 }
1015
DynamicLoadLibFctDynamicLoadLibFct1016 DynamicLoadLibFct(LPCTSTR moduleName, LPCSTR name)
1017 {
1018 _hModule = LoadLibrary(moduleName);
1019
1020 _fct = (FCT) GetProcAddress(_hModule, name);
1021 }
1022
~DynamicLoadLibFctDynamicLoadLibFct1023 ~DynamicLoadLibFct()
1024 {
1025 FreeLibrary(_hModule);
1026 }
1027
1028 FCT operator*() const {return _fct;}
1029 operator bool() const {return _fct? true: false;}
1030
1031 protected:
1032 HMODULE _hModule;
1033 FCT _fct;
1034 };
1035
1036
1037 struct Context
1038 {
ContextContext1039 Context(const char* ctx)
1040 : _ctx(ctx)
1041 {
1042 _last = s_current;
1043 s_current = this;
1044 }
1045
ContextContext1046 Context(const char* ctx, LPCSTR obj)
1047 : _ctx(ctx),
1048 _obj(obj)
1049 {
1050 _last = s_current;
1051 s_current = this;
1052 }
1053
ContextContext1054 Context(const char* ctx, LPCWSTR obj)
1055 : _ctx(ctx),
1056 _obj(obj)
1057 {
1058 _last = s_current;
1059 s_current = this;
1060 }
1061
ContextContext1062 Context(const Context& other)
1063 : _ctx(other._ctx),
1064 _obj(other._obj)
1065 {
1066 _last = NULL;
1067 }
1068
~ContextContext1069 ~Context()
1070 {
1071 if (_last) {
1072 s_current = _last;
1073 _last = NULL;
1074 }
1075 }
1076
1077 String toString() const;
1078 String getStackTrace() const;
1079
1080 const char* _ctx;
1081 String _obj;
1082
currentContext1083 static Context& current() {return *s_current;}
1084
1085 protected:
1086 Context* _last;
1087
1088 static Context* s_current; ///@todo use TLS
1089 static Context s_main;
1090 };
1091
1092 #define CONTEXT_OBJ __ctx__._obj
1093 #define CONTEXT(c) Context __ctx__(c)
1094 #define CURRENT_CONTEXT Context::current()
1095 #define OBJ_CONTEXT(c, o) Context __ctx__(c, o)
1096
1097
1098 extern bool SplitFileSysURL(LPCTSTR url, String& dir_out, String& fname_out);
1099
1100
1101 #endif // __cplusplus
1102