mirror of
https://github.com/reactos/reactos.git
synced 2024-08-19 18:02:55 +00:00
1102 lines
22 KiB
C++
1102 lines
22 KiB
C++
/*
|
|
* Copyright 2003, 2004, 2005 Martin Fuchs
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
|
|
//
|
|
// Explorer clone
|
|
//
|
|
// utility.h
|
|
//
|
|
// Martin Fuchs, 23.07.2003
|
|
//
|
|
|
|
// standard windows headers
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#define WIN32_EXTRA_LEAN
|
|
#define WIN32_NO_STATUS
|
|
#define _INC_WINDOWS
|
|
#define COM_NO_WINDOWS_H
|
|
#include <stdarg.h>
|
|
#include <windef.h>
|
|
#include <winbase.h>
|
|
#include <winuser.h>
|
|
|
|
//#include <undocuser.h>
|
|
|
|
// Unicode support
|
|
#if defined(UNICODE) && !defined(_UNICODE)
|
|
#define _UNICODE
|
|
#endif
|
|
#include <tchar.h>
|
|
|
|
#include <windowsx.h> // for SelectBrush(), ListBox_SetSel(), SubclassWindow(), ...
|
|
#include <commctrl.h>
|
|
|
|
#include <objbase.h>
|
|
//#include <oleauto.h> // for VARIANT
|
|
|
|
//#include <malloc.h> // for alloca()
|
|
#include <assert.h>
|
|
//#include <stdlib.h> // for _MAX_DIR, ...
|
|
#include <stdio.h> // for sprintf()
|
|
//#include <time.h>
|
|
|
|
#ifdef __cplusplus
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(disable: 4786) // disable warnings about too long debug information symbols
|
|
#endif
|
|
|
|
// STL headers for strings and streams
|
|
#include <string>
|
|
#include <iostream>
|
|
using namespace std;
|
|
|
|
#endif /* __cplusplus */
|
|
|
|
#ifndef _MAX_PATH
|
|
#define _MAX_DRIVE 3
|
|
#define _MAX_FNAME 256
|
|
#define _MAX_DIR _MAX_FNAME
|
|
#define _MAX_EXT _MAX_FNAME
|
|
#define _MAX_PATH 260
|
|
#endif
|
|
|
|
#define W_VER_NT 0 // constant for HIWORD(GetVersion())>>14
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
#define for if (0) {} else for
|
|
|
|
#ifdef _countof
|
|
#define COUNTOF _countof
|
|
#else
|
|
#define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
|
|
#endif
|
|
|
|
|
|
#define BUFFER_LEN 2048
|
|
|
|
|
|
extern void _log_(LPCTSTR txt);
|
|
|
|
#define LOG(txt) _log_(txt)
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
#define LONGLONGARG TEXT("I64")
|
|
#else
|
|
#define LONGLONGARG TEXT("L")
|
|
#endif
|
|
|
|
|
|
#ifndef _tcsrchr
|
|
#ifdef UNICODE
|
|
#define _tcsrchr wcsrchr
|
|
#else
|
|
#define _tcsrchr strrchr
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef _stprintf
|
|
#ifdef UNICODE
|
|
#define _stprintf wcsprintf
|
|
#else
|
|
#define _stprintf sprintf
|
|
#endif
|
|
#endif
|
|
|
|
#define U2A(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, -1, d, l, NULL, NULL)
|
|
#define U2nA(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, l, d, l, NULL, NULL)
|
|
#define A2U(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, -1, d, l)
|
|
#define A2nU(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, l, d, l)
|
|
|
|
|
|
#ifdef __WINE__
|
|
#ifdef UNICODE
|
|
extern void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext);
|
|
#else
|
|
extern void _splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext);
|
|
#endif
|
|
#define _tcsnicmp strncasecmp
|
|
#define _tcsicoll strcasecmp
|
|
#endif
|
|
|
|
#ifndef FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
|
|
#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
|
|
#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
|
|
#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
|
|
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
|
|
#endif
|
|
|
|
|
|
#define SetDlgCtrlID(hwnd, id) SetWindowLongPtr(hwnd, GWL_ID, id)
|
|
#define SetWindowStyle(hwnd, val) (DWORD)SetWindowLongPtr(hwnd, GWL_STYLE, val)
|
|
#define SetWindowExStyle(h, val) (DWORD)SetWindowLongPtr(hwnd, GWL_EXSTYLE, val)
|
|
#define Window_SetIcon(hwnd, type, hicon) (HICON)SendMessage(hwnd, WM_SETICON, type, (LPARAM)(hicon))
|
|
|
|
|
|
// center window in respect to its parent window
|
|
extern void CenterWindow(HWND hwnd);
|
|
|
|
// move window into visibility
|
|
extern void MoveVisible(HWND hwnd);
|
|
|
|
// display error message
|
|
extern void display_error(HWND hwnd, DWORD error);
|
|
|
|
// convert time_t to WIN32 FILETIME
|
|
extern BOOL time_to_filetime(const time_t* t, FILETIME* ftime);
|
|
|
|
// search for windows of a specific classname
|
|
extern int find_window_class(LPCTSTR classname);
|
|
|
|
// create a directory with all missing parent directories
|
|
BOOL RecursiveCreateDirectory(LPCTSTR path_in);
|
|
|
|
// read DWORD value from registry
|
|
DWORD RegGetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD def);
|
|
|
|
// write DWORD value to registry
|
|
BOOL RegSetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD value);
|
|
|
|
// test for existing directory
|
|
BOOL exists_path(LPCTSTR path);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
} // extern "C"
|
|
#endif
|
|
|
|
|
|
// secure CRT functions
|
|
//@@ _MS_VER: temporarily needed for the ReactOS build environment
|
|
#if defined(__STDC_WANT_SECURE_LIB__) && defined(_MS_VER) // for VS 2005: _MSC_VER>=1400
|
|
|
|
#define _stprintf_s1 _stprintf_s
|
|
#define _stprintf_s2 _stprintf_s
|
|
|
|
#else // __STDC_WANT_SECURE_LIB__
|
|
|
|
#define strcpy_s(d, l, s) strcpy(d, s)
|
|
#define wcscpy_s(d, l, s) wcscpy(d, s)
|
|
#define wcsncpy_s(d, l, s, n) wcsncpy(d, s, n)
|
|
|
|
#if defined(_tcscpy) && !defined(_tcscpy_s)
|
|
#define _tcscpy_s(d, l, s) _tcscpy(d, s)
|
|
#endif
|
|
|
|
#if defined(_tsplitpath) && !defined(_tsplitpath_s)
|
|
#define _tsplitpath_s(f, d,dl, p,pl, n,nl, e,el) _tsplitpath(f, d, p, n, e)
|
|
#else
|
|
#define _wsplitpath_s(f, d,dl, p,pl, n,nl, e,el) _wsplitpath(f, d, p, n, e)
|
|
#define _splitpath_s(f, d,dl, p,pl, n,nl, e,el) _splitpath(f, d, p, n, e)
|
|
#endif
|
|
|
|
#define _stprintf_s1(b, l, f, p1) _stprintf(b, f, p1)
|
|
#define _stprintf_s2(b, l, f, p1,p2) _stprintf(b, f, p1,p2)
|
|
|
|
#endif // __STDC_WANT_SECURE_LIB__
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
// containers
|
|
#include <map>
|
|
#include <set>
|
|
#include <list>
|
|
#include <stack>
|
|
#include <vector>
|
|
|
|
|
|
/* not necessary with correct include file order for comdef.h ("<MS PSDK>\include" path first) */
|
|
#if _MSC_VER>=1300 // VS.Net
|
|
#define _NO_COMUTIL
|
|
#endif
|
|
|
|
|
|
#if defined(_MSC_VER) && !defined(_NO_COMUTIL)
|
|
|
|
// COM utility headers
|
|
#include <comdef.h>
|
|
using namespace _com_util;
|
|
|
|
#endif // _MSC_VER && !_NO_COMUTIL
|
|
|
|
|
|
// launch a program or document file
|
|
extern BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow=SW_SHOWNORMAL, LPCTSTR parameters=NULL);
|
|
#ifdef UNICODE
|
|
extern BOOL launch_fileA(HWND hwnd, LPSTR cmd, UINT nCmdShow=SW_SHOWNORMAL, LPCSTR parameters=NULL);
|
|
#else
|
|
#define launch_fileA launch_file
|
|
#endif
|
|
|
|
// call an DLL export like rundll32
|
|
extern BOOL RunDLL(HWND hwnd, LPCTSTR dllname, LPCSTR procname, LPCTSTR cmdline, UINT nCmdShow);
|
|
|
|
// launch control panel applet
|
|
extern BOOL launch_cpanel(HWND hwnd, LPCTSTR applet);
|
|
|
|
|
|
/// initialization of windows common controls
|
|
struct CommonControlInit
|
|
{
|
|
CommonControlInit(DWORD flags=ICC_LISTVIEW_CLASSES|ICC_TREEVIEW_CLASSES|ICC_BAR_CLASSES|ICC_PROGRESS_CLASS|ICC_COOL_CLASSES)
|
|
{
|
|
INITCOMMONCONTROLSEX icc = {sizeof(INITCOMMONCONTROLSEX), flags};
|
|
|
|
InitCommonControlsEx(&icc);
|
|
}
|
|
};
|
|
|
|
|
|
/// wait cursor
|
|
|
|
struct WaitCursor ///@todo integrate with WM_SETCURSOR to enable multithreaded background tasks as program launching
|
|
{
|
|
WaitCursor()
|
|
{
|
|
_old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
|
|
}
|
|
|
|
~WaitCursor()
|
|
{
|
|
SetCursor(_old_cursor);
|
|
}
|
|
|
|
protected:
|
|
HCURSOR _old_cursor;
|
|
};
|
|
|
|
|
|
/// base of all structures storing a window handle
|
|
struct WindowHandle
|
|
{
|
|
WindowHandle(HWND hwnd=0)
|
|
: _hwnd(hwnd) {}
|
|
|
|
operator HWND() const {return _hwnd;}
|
|
HWND* operator&() {return &_hwnd;}
|
|
|
|
protected:
|
|
HWND _hwnd;
|
|
};
|
|
|
|
|
|
/// locally hide a window
|
|
struct HiddenWindow : public WindowHandle
|
|
{
|
|
HiddenWindow(HWND hwnd)
|
|
: WindowHandle(IsWindowVisible(hwnd)? hwnd: 0)
|
|
{
|
|
if (_hwnd)
|
|
SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
|
|
}
|
|
|
|
~HiddenWindow()
|
|
{
|
|
if (_hwnd)
|
|
SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
|
|
}
|
|
};
|
|
|
|
|
|
/// critical section wrapper
|
|
|
|
struct CritSect : public CRITICAL_SECTION
|
|
{
|
|
CritSect()
|
|
{
|
|
InitializeCriticalSection(this);
|
|
}
|
|
|
|
~CritSect()
|
|
{
|
|
DeleteCriticalSection(this);
|
|
}
|
|
};
|
|
|
|
|
|
/// Lock protects a code section utilizing a critical section
|
|
|
|
struct Lock
|
|
{
|
|
Lock(CritSect& crit_sect)
|
|
: _crit_sect(crit_sect)
|
|
{
|
|
EnterCriticalSection(&crit_sect);
|
|
}
|
|
|
|
~Lock()
|
|
{
|
|
LeaveCriticalSection(&_crit_sect);
|
|
}
|
|
|
|
protected:
|
|
CritSect& _crit_sect;
|
|
};
|
|
|
|
|
|
/// Thread base class
|
|
|
|
struct Thread
|
|
{
|
|
Thread()
|
|
: _alive(false),
|
|
_destroy(false)
|
|
{
|
|
_hThread = INVALID_HANDLE_VALUE;
|
|
_evtFinish = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
}
|
|
|
|
virtual ~Thread()
|
|
{
|
|
Stop();
|
|
|
|
CloseHandle(_evtFinish);
|
|
CloseHandle(_hThread);
|
|
|
|
if (_destroy)
|
|
delete this;
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
if (!_alive) {
|
|
_alive = true;
|
|
_hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
|
|
}
|
|
}
|
|
|
|
void Stop()
|
|
{
|
|
SetEvent(_evtFinish);
|
|
|
|
if (_alive) {
|
|
{
|
|
Lock lock(_crit_sect);
|
|
_alive = false;
|
|
}
|
|
|
|
// wait for finishing
|
|
WaitForSingleObject(_hThread, INFINITE);
|
|
}
|
|
}
|
|
|
|
virtual int Run() = 0;
|
|
|
|
bool is_alive() const {return _alive;}
|
|
|
|
CritSect _crit_sect;
|
|
|
|
protected:
|
|
static DWORD WINAPI ThreadProc(void* para);
|
|
|
|
HANDLE _hThread;
|
|
HANDLE _evtFinish;
|
|
bool _alive;
|
|
bool _destroy;
|
|
};
|
|
|
|
|
|
// window utilities
|
|
|
|
/// ClientRect retreives the client area rectangle of a window.
|
|
struct ClientRect : public RECT
|
|
{
|
|
ClientRect(HWND hwnd)
|
|
{
|
|
GetClientRect(hwnd, this);
|
|
}
|
|
|
|
operator LPRECT() {return this;}
|
|
|
|
POINT& pos() {return *(LPPOINT)this;}
|
|
};
|
|
|
|
/// ClientRect retreives the window rectangle of a window.
|
|
struct WindowRect : public RECT
|
|
{
|
|
WindowRect(HWND hwnd)
|
|
{
|
|
GetWindowRect(hwnd, this);
|
|
}
|
|
|
|
operator LPRECT() {return this;}
|
|
|
|
POINT& pos() {return *(LPPOINT)this;}
|
|
};
|
|
|
|
/// PointL encapsulates the POINT structure into a C++ object.
|
|
struct Point : public POINT
|
|
{
|
|
Point(LONG x_, LONG y_)
|
|
{
|
|
x = x_;
|
|
y = y_;
|
|
}
|
|
|
|
// constructor for being used in processing WM_MOUSEMOVE, WM_LBUTTONDOWN, ... messages
|
|
Point(LPARAM lparam)
|
|
{
|
|
x = GET_X_LPARAM(lparam);
|
|
y = GET_Y_LPARAM(lparam);
|
|
}
|
|
|
|
operator LPPOINT() {return this;}
|
|
};
|
|
|
|
|
|
/// transform coordinates in a RECT from client to screen coordiantes
|
|
inline void ClientToScreen(HWND hwnd, RECT* prect)
|
|
{::ClientToScreen(hwnd,(LPPOINT)&prect->left); ::ClientToScreen(hwnd,(LPPOINT)&prect->right);}
|
|
|
|
/// transform coordinates in a RECT from screen to client coordiantes
|
|
inline void ScreenToClient(HWND hwnd, RECT* prect)
|
|
{::ScreenToClient(hwnd,(LPPOINT)&prect->left); ::ScreenToClient(hwnd,(LPPOINT)&prect->right);}
|
|
|
|
|
|
/// structure containing information about full screen display of the frame window
|
|
struct FullScreenParameters
|
|
{
|
|
FullScreenParameters()
|
|
: _mode(FALSE)
|
|
{
|
|
}
|
|
|
|
BOOL _mode;
|
|
RECT _orgPos;
|
|
BOOL _wasZoomed;
|
|
};
|
|
|
|
|
|
// drawing utilities
|
|
|
|
/// PaintCanvas is a encapsulation of device contexts managed by BeginPaint()/EndPaint().
|
|
struct PaintCanvas : public PAINTSTRUCT
|
|
{
|
|
PaintCanvas(HWND hwnd)
|
|
: _hwnd(hwnd)
|
|
{
|
|
BeginPaint(hwnd, this);
|
|
}
|
|
|
|
~PaintCanvas()
|
|
{
|
|
EndPaint(_hwnd, this);
|
|
}
|
|
|
|
operator HDC() const {return hdc;}
|
|
|
|
protected:
|
|
HWND _hwnd;
|
|
};
|
|
|
|
/// Canvas is a encapsulation of device contexts.
|
|
struct Canvas
|
|
{
|
|
Canvas(HDC hdc) : _hdc(hdc) {}
|
|
|
|
operator HDC() {return _hdc;}
|
|
|
|
protected:
|
|
HDC _hdc;
|
|
};
|
|
|
|
/// WindowCanvas is a encapsulation of client area device contexts.
|
|
struct WindowCanvas : public Canvas
|
|
{
|
|
WindowCanvas(HWND hwnd)
|
|
: Canvas(GetDC(hwnd)), _hwnd(hwnd) {}
|
|
|
|
~WindowCanvas() {ReleaseDC(_hwnd, _hdc);}
|
|
|
|
protected:
|
|
HWND _hwnd;
|
|
};
|
|
|
|
|
|
// double buffering classes
|
|
|
|
/// Memory Canvas creates and destroys memory devoce contexts.
|
|
struct MemCanvas : public Canvas
|
|
{
|
|
MemCanvas(HDC hdc=0)
|
|
: Canvas(CreateCompatibleDC(hdc)) {assert(_hdc);}
|
|
|
|
~MemCanvas() {DeleteDC(_hdc);}
|
|
};
|
|
|
|
/// SelectedBitmap is used to localy select bitmaps into device contexts.
|
|
struct SelectedBitmap
|
|
{
|
|
SelectedBitmap(HDC hdc, HBITMAP hbmp)
|
|
: _hdc(hdc), _old_hbmp(SelectBitmap(hdc, hbmp)) {}
|
|
|
|
~SelectedBitmap() {DeleteObject(SelectBitmap(_hdc, _old_hbmp));}
|
|
|
|
protected:
|
|
HDC _hdc;
|
|
HBITMAP _old_hbmp;
|
|
};
|
|
|
|
/// BufferCanvas manages offscreen bitmaps selected into memory device contexts.
|
|
struct BufferCanvas : public MemCanvas
|
|
{
|
|
BufferCanvas(HDC hdc, int x, int y, int w, int h)
|
|
: MemCanvas(hdc), _hdctarg(hdc),
|
|
_x(x), _y(y), _w(w), _h(h),
|
|
_bmp(_hdc, CreateCompatibleBitmap(hdc, w, h)) {}
|
|
|
|
BufferCanvas(HDC hdc, const RECT& rect)
|
|
: MemCanvas(hdc), _hdctarg(hdc),
|
|
_x(rect.left), _y(rect.top), _w(rect.right-rect.left), _h(rect.bottom-rect.top),
|
|
_bmp(_hdc, CreateCompatibleBitmap(hdc, _w, _h)) {}
|
|
|
|
protected:
|
|
HDC _hdctarg;
|
|
int _x, _y, _w, _h;
|
|
SelectedBitmap _bmp;
|
|
};
|
|
|
|
/// BufferedCanvas enables double buffering for a device context.
|
|
struct BufferedCanvas : public BufferCanvas
|
|
{
|
|
BufferedCanvas(HDC hdc, int x, int y, int w, int h, DWORD mode=SRCCOPY)
|
|
: BufferCanvas(hdc, x, y, w, h), _mode(mode) {}
|
|
|
|
BufferedCanvas(HDC hdc, const RECT& rect, DWORD mode=SRCCOPY)
|
|
: BufferCanvas(hdc, rect), _mode(mode) {}
|
|
|
|
~BufferedCanvas() {BitBlt(_hdctarg, _x, _y, _w, _h, _hdc, 0, 0, _mode);}
|
|
|
|
DWORD _mode;
|
|
};
|
|
|
|
/// BufferedPaintCanvas extends PaintCanvas for double buffering.
|
|
struct BufferedPaintCanvas : public PaintCanvas, public BufferedCanvas
|
|
{
|
|
BufferedPaintCanvas(HWND hwnd)
|
|
: PaintCanvas(hwnd),
|
|
BufferedCanvas(PAINTSTRUCT::hdc, 0, 0, rcPaint.right, rcPaint.bottom)
|
|
{
|
|
}
|
|
|
|
operator HDC() {return BufferedCanvas::_hdc;}
|
|
};
|
|
|
|
|
|
/// TextColor locally selects a text color for drawing.
|
|
struct TextColor
|
|
{
|
|
TextColor(HDC hdc, COLORREF color)
|
|
: _hdc(hdc), _old_color(SetTextColor(hdc, color)) {}
|
|
|
|
~TextColor() {SetTextColor(_hdc, _old_color);}
|
|
|
|
protected:
|
|
HDC _hdc;
|
|
COLORREF _old_color;
|
|
};
|
|
|
|
/// BkMode locally sets the background mode for drawing.
|
|
struct BkMode
|
|
{
|
|
BkMode(HDC hdc, int bkmode)
|
|
: _hdc(hdc), _old_bkmode(SetBkMode(hdc, bkmode)) {}
|
|
|
|
~BkMode() {SetBkMode(_hdc, _old_bkmode);}
|
|
|
|
protected:
|
|
HDC _hdc;
|
|
COLORREF _old_bkmode;
|
|
};
|
|
|
|
/// FontSelection locally selects a font for drawing.
|
|
struct FontSelection
|
|
{
|
|
FontSelection(HDC hdc, HFONT hFont)
|
|
: _hdc(hdc), _old_hFont(SelectFont(hdc, hFont)) {}
|
|
|
|
~FontSelection() {SelectFont(_hdc, _old_hFont);}
|
|
|
|
protected:
|
|
HDC _hdc;
|
|
HFONT _old_hFont;
|
|
};
|
|
|
|
/// BitmapSelection locally selects a bitmap into a device context.
|
|
struct BitmapSelection
|
|
{
|
|
BitmapSelection(HDC hdc, HBITMAP hBmp)
|
|
: _hdc(hdc), _old_hBmp(SelectBitmap(hdc, hBmp)) {}
|
|
|
|
~BitmapSelection() {SelectBitmap(_hdc, _old_hBmp);}
|
|
|
|
protected:
|
|
HDC _hdc;
|
|
HBITMAP _old_hBmp;
|
|
};
|
|
|
|
/// BrushSelection locally selects a brush into a device context.
|
|
struct BrushSelection
|
|
{
|
|
BrushSelection(HDC hdc, HBRUSH hBrush)
|
|
: _hdc(hdc), _old_hBrush(SelectBrush(hdc, hBrush)) {}
|
|
|
|
~BrushSelection() {SelectBrush(_hdc, _old_hBrush);}
|
|
|
|
protected:
|
|
HDC _hdc;
|
|
HBRUSH _old_hBrush;
|
|
};
|
|
|
|
|
|
/// Popup Menus
|
|
struct PopupMenu
|
|
{
|
|
PopupMenu()
|
|
: _hmenu(CreatePopupMenu())
|
|
{
|
|
}
|
|
|
|
~PopupMenu()
|
|
{
|
|
DestroyMenu(_hmenu);
|
|
}
|
|
|
|
PopupMenu(UINT nid);
|
|
|
|
operator HMENU() {return _hmenu;}
|
|
|
|
void Append(UINT id, LPCTSTR str, UINT flags=MF_STRING)
|
|
{
|
|
AppendMenu(_hmenu, flags, id, str);
|
|
}
|
|
|
|
int TrackPopupMenu(HWND hwnd, const POINT& pt, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON, LPTPMPARAMS tpm=NULL) {
|
|
return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, tpm);
|
|
}
|
|
|
|
int PopupContextMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
|
|
POINT pt;
|
|
pt.x = pos.x;
|
|
pt.y = pos.y;
|
|
return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
|
|
}
|
|
|
|
int TrackPopupMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) {
|
|
POINT pt;
|
|
pt.x = pos.x;
|
|
pt.y = pos.y;
|
|
ClientToScreen(hwnd, &pt);
|
|
return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
|
|
}
|
|
|
|
int TrackPopupMenuAtCursor(HWND hwnd, UINT flags=TPM_LEFTBUTTON) {
|
|
POINT pt; GetCursorPos(&pt);
|
|
return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL);
|
|
}
|
|
|
|
int TrackPopupMenuAtPos(HWND hwnd, DWORD pos, UINT flags=TPM_LEFTBUTTON) {
|
|
return TrackPopupMenuEx(_hmenu, flags, GET_X_LPARAM(pos), GET_Y_LPARAM(pos), hwnd, NULL);
|
|
}
|
|
|
|
protected:
|
|
HMENU _hmenu;
|
|
};
|
|
|
|
|
|
struct Variant : public VARIANT
|
|
{
|
|
Variant() {VariantInit(this);}
|
|
Variant(const VARIANT& var);
|
|
Variant(const VARIANT* var);
|
|
~Variant();
|
|
|
|
operator long() const;
|
|
operator bool() const;
|
|
operator VARIANT_BOOL() const;
|
|
operator IDispatch*() const;
|
|
};
|
|
|
|
|
|
struct BStr
|
|
{
|
|
BStr()
|
|
{
|
|
_p = NULL;
|
|
}
|
|
|
|
BStr(const BSTR s)
|
|
{
|
|
_p = SysAllocString(s);
|
|
}
|
|
|
|
BStr(LPCSTR s)
|
|
{
|
|
WCHAR b[BUFFER_LEN];
|
|
|
|
if (s)
|
|
_p = SysAllocStringLen(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1);
|
|
else
|
|
_p = NULL;
|
|
}
|
|
|
|
BStr(LPCWSTR s)
|
|
{
|
|
_p = SysAllocString(s);
|
|
}
|
|
|
|
BStr(const VARIANT& var)
|
|
: _p(NULL)
|
|
{
|
|
assign(var);
|
|
}
|
|
|
|
~BStr()
|
|
{
|
|
SysFreeString(_p);
|
|
}
|
|
|
|
void assign(BSTR s);
|
|
void assign(const VARIANT& var);
|
|
|
|
operator BSTR() const
|
|
{
|
|
return _p? _p: (BSTR)L"";
|
|
}
|
|
|
|
int length() const
|
|
{
|
|
return _p? wcslen(_p): 0;
|
|
}
|
|
|
|
protected:
|
|
BSTR _p;
|
|
};
|
|
|
|
|
|
/// string class for TCHAR strings
|
|
struct String
|
|
#ifdef UNICODE
|
|
: public wstring
|
|
#else
|
|
: public string
|
|
#endif
|
|
{
|
|
#ifdef UNICODE
|
|
typedef wstring super;
|
|
#else
|
|
typedef string super;
|
|
#endif
|
|
|
|
String() {}
|
|
|
|
String(LPCTSTR s) {if (s) super::assign(s);}
|
|
String(LPCTSTR s, int l) : super(s, l) {}
|
|
|
|
String(const super& other) : super(other) {}
|
|
String(const String& other) : super(other) {}
|
|
|
|
#ifdef UNICODE
|
|
String(LPCSTR s) {assign(s);}
|
|
String(LPCSTR s, int l) {assign(s, l);}
|
|
String(const string& other) {assign(other.c_str());}
|
|
String& operator=(LPCSTR s) {assign(s); return *this;}
|
|
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();}
|
|
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();}
|
|
void assign(const BStr& s) {int l = s.length(); super::assign(s, l);}
|
|
#else
|
|
String(LPCWSTR s) {assign(s);}
|
|
String(LPCWSTR s, int l) {assign(s, l);}
|
|
String(const wstring& other) {assign(other.c_str());}
|
|
String& operator=(LPCWSTR s) {assign(s); return *this;}
|
|
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();}
|
|
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();}
|
|
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();}
|
|
#endif
|
|
String(const BStr& s) {assign(s);}
|
|
String& operator=(const BStr& s) {assign(s); return *this;}
|
|
|
|
String& operator=(LPCTSTR s) {if (s) super::assign(s); else erase(); return *this;}
|
|
String& operator=(const super& s) {super::assign(s); return *this;}
|
|
void assign(LPCTSTR s) {super::assign(s);}
|
|
void assign(LPCTSTR s, int l) {super::assign(s, l);}
|
|
|
|
operator LPCTSTR() const {return c_str();}
|
|
|
|
#ifdef UNICODE
|
|
operator string() const {char b[BUFFER_LEN]; return string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN, 0, 0)-1);}
|
|
#else
|
|
operator wstring() const {WCHAR b[BUFFER_LEN]; return wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN)-1);}
|
|
#endif
|
|
|
|
LPTSTR str() {return (LPTSTR)data();} /// return modifyable character string pointer
|
|
|
|
String& printf(LPCTSTR fmt, ...)
|
|
{
|
|
va_list l;
|
|
TCHAR b[BUFFER_LEN];
|
|
|
|
va_start(l, fmt);
|
|
super::assign(b, _vsntprintf(b, COUNTOF(b), fmt, l));
|
|
va_end(l);
|
|
|
|
return *this;
|
|
}
|
|
|
|
String& vprintf(LPCTSTR fmt, va_list l)
|
|
{
|
|
TCHAR b[BUFFER_LEN];
|
|
|
|
super::assign(b, _vsntprintf(b, COUNTOF(b), fmt, l));
|
|
|
|
return *this;
|
|
}
|
|
|
|
String& appendf(LPCTSTR fmt, ...)
|
|
{
|
|
va_list l;
|
|
TCHAR b[BUFFER_LEN];
|
|
|
|
va_start(l, fmt);
|
|
super::append(b, _vsntprintf(b, COUNTOF(b), fmt, l));
|
|
va_end(l);
|
|
|
|
return *this;
|
|
}
|
|
|
|
String& vappendf(LPCTSTR fmt, va_list l)
|
|
{
|
|
TCHAR b[BUFFER_LEN];
|
|
|
|
super::append(b, _vsntprintf(b, COUNTOF(b), fmt, l));
|
|
|
|
return *this;
|
|
}
|
|
|
|
void toLower()
|
|
{
|
|
if (!empty())
|
|
CharLower(str());
|
|
}
|
|
};
|
|
|
|
#define _STRING_DEFINED
|
|
|
|
|
|
struct FmtString : public String
|
|
{
|
|
FmtString(LPCTSTR fmt, ...)
|
|
{
|
|
va_list l;
|
|
|
|
va_start(l, fmt);
|
|
vprintf(fmt, l);
|
|
va_end(l);
|
|
}
|
|
};
|
|
|
|
|
|
#ifdef UNICODE
|
|
|
|
struct ANS
|
|
{
|
|
ANS(LPCWSTR s)
|
|
{
|
|
int l = wcslen(s) + 1;
|
|
_str = (LPSTR) malloc(2*l);
|
|
|
|
if (WideCharToMultiByte(CP_ACP, 0, s, -1, _str, 2*l, 0, 0) <= 0)
|
|
*_str = '\0';
|
|
}
|
|
|
|
~ANS()
|
|
{
|
|
free(_str);
|
|
}
|
|
|
|
operator LPCSTR() {return _str;}
|
|
|
|
protected:
|
|
LPSTR _str;
|
|
};
|
|
|
|
#define UNC(x) ((LPCWSTR)(x))
|
|
|
|
#else
|
|
|
|
#define ANS(x) ((LPCSTR)(x))
|
|
|
|
struct UNC
|
|
{
|
|
UNC(LPCSTR s)
|
|
{
|
|
int l = strlen(s) + 1;
|
|
_str = (LPWSTR) malloc(2*l);
|
|
|
|
if (_str && MultiByteToWideChar(CP_ACP, 0, s, -1, _str, l) <= 0)
|
|
*_str = '\0';
|
|
}
|
|
|
|
~UNC()
|
|
{
|
|
free(_str);
|
|
}
|
|
|
|
operator LPCWSTR() {return _str;}
|
|
|
|
protected:
|
|
LPWSTR _str;
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
// determine windows version string
|
|
String get_windows_version_str();
|
|
|
|
|
|
/// link dynamicly to functions by using GetModuleHandle() and GetProcAddress()
|
|
template<typename FCT> struct DynamicFct
|
|
{
|
|
DynamicFct(LPCTSTR moduleName, UINT ordinal)
|
|
{
|
|
HMODULE hModule = GetModuleHandle(moduleName);
|
|
|
|
_fct = (FCT) GetProcAddress(hModule, (LPCSTR)ordinal);
|
|
}
|
|
|
|
DynamicFct(LPCTSTR moduleName, LPCSTR name)
|
|
{
|
|
HMODULE hModule = GetModuleHandle(moduleName);
|
|
|
|
_fct = (FCT) GetProcAddress(hModule, name);
|
|
}
|
|
|
|
FCT operator*() const {return _fct;}
|
|
operator bool() const {return _fct? true: false;}
|
|
|
|
protected:
|
|
FCT _fct;
|
|
};
|
|
|
|
|
|
/// link dynamicly to functions by using LoadLibrary() and GetProcAddress()
|
|
template<typename FCT> struct DynamicLoadLibFct
|
|
{
|
|
DynamicLoadLibFct(LPCTSTR moduleName, UINT ordinal)
|
|
{
|
|
_hModule = LoadLibrary(moduleName);
|
|
|
|
_fct = (FCT) GetProcAddress(_hModule, (LPCSTR)ordinal);
|
|
}
|
|
|
|
DynamicLoadLibFct(LPCTSTR moduleName, LPCSTR name)
|
|
{
|
|
_hModule = LoadLibrary(moduleName);
|
|
|
|
_fct = (FCT) GetProcAddress(_hModule, name);
|
|
}
|
|
|
|
~DynamicLoadLibFct()
|
|
{
|
|
FreeLibrary(_hModule);
|
|
}
|
|
|
|
FCT operator*() const {return _fct;}
|
|
operator bool() const {return _fct? true: false;}
|
|
|
|
protected:
|
|
HMODULE _hModule;
|
|
FCT _fct;
|
|
};
|
|
|
|
|
|
struct Context
|
|
{
|
|
Context(const char* ctx)
|
|
: _ctx(ctx)
|
|
{
|
|
_last = s_current;
|
|
s_current = this;
|
|
}
|
|
|
|
Context(const char* ctx, LPCSTR obj)
|
|
: _ctx(ctx),
|
|
_obj(obj)
|
|
{
|
|
_last = s_current;
|
|
s_current = this;
|
|
}
|
|
|
|
Context(const char* ctx, LPCWSTR obj)
|
|
: _ctx(ctx),
|
|
_obj(obj)
|
|
{
|
|
_last = s_current;
|
|
s_current = this;
|
|
}
|
|
|
|
Context(const Context& other)
|
|
: _ctx(other._ctx),
|
|
_obj(other._obj)
|
|
{
|
|
_last = NULL;
|
|
}
|
|
|
|
~Context()
|
|
{
|
|
if (_last) {
|
|
s_current = _last;
|
|
_last = NULL;
|
|
}
|
|
}
|
|
|
|
String toString() const;
|
|
String getStackTrace() const;
|
|
|
|
const char* _ctx;
|
|
String _obj;
|
|
|
|
static Context& current() {return *s_current;}
|
|
|
|
protected:
|
|
Context* _last;
|
|
|
|
static Context* s_current; ///@todo use TLS
|
|
static Context s_main;
|
|
};
|
|
|
|
#define CONTEXT_OBJ __ctx__._obj
|
|
#define CONTEXT(c) Context __ctx__(c)
|
|
#define CURRENT_CONTEXT Context::current()
|
|
#define OBJ_CONTEXT(c, o) Context __ctx__(c, o)
|
|
|
|
|
|
extern bool SplitFileSysURL(LPCTSTR url, String& dir_out, String& fname_out);
|
|
|
|
|
|
#endif // __cplusplus
|