Micro framework to generate win32 applications.
Sample:
// Windows Header Files:
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include "win32express.h"
#include "resource.h"
class AboutDlg : public Dialog<AboutDlg, IDD_ABOUT>
{
void About()
{
}
void OnClose()
{
EndDialog(IDCANCEL);
}
void OnOk()
{
EndDialog(IDCANCEL);
PostQuitMessage(1);
}
public:
BEGIN_MSG_MAP(AboutDlg)
S_COMMAND_ID_HANDLER(IDCANCEL, OnClose)
S_COMMAND_ID_HANDLER(IDOK, OnOk)
S_COMMAND_ID_HANDLER(IDM_ABOUT1, About)
END_MSG_MAP()
AboutDlg(HWND hParent = NULL) : Dialog<AboutDlg, IDD_ABOUT>(hParent)
{
}
void OnPaint(HDC hdc)
{
::TextOut(hdc, 10,10,L"hello", 6);
}
};
class Doc : public Window<Doc, IDI_ICON1, IDR_MENU1>
{
void Exit()
{
DestroyWindow(m_hWnd);
PostQuitMessage(0);
}
void About()
{
AboutDlg dlg(m_hWnd);
dlg.ShowDialog();
}
public:
BEGIN_MSG_MAP(AboutDlg)
S_COMMAND_ID_HANDLER(IDM_ABOUT1, About)
S_COMMAND_ID_HANDLER(IDM_EXIT1, Exit)
END_MSG_MAP()
void OnPaint(HDC hdc)
{
::TextOut(hdc, 10,10,L"hello", 6);
}
};
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
Doc doc;
doc.Create();
return RunMessageLoop();
}
Header file
// Copyright (C) 2010, Thiago Adams (thiago.adams@gmail.com)
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//This is a experimental code.
#pragma once
#include <windows.h>
#include <commctrl.h>
#include <vector>
#include <string>
#ifndef ASSERT
#include <cassert>
#define ASSERT assert
#endif
#include <string.h>
template<class T>
T* GetWindowDocument(HWND hWnd)
{
T *pDoc = reinterpret_cast<T *>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(hWnd, GWLP_USERDATA)));
return pDoc;
}
template<class T>
T* SetWindowDocument(HWND hWnd, T* pReceiver)
{
LONG_PTR lptr = ::SetWindowLongPtrW(
hWnd,
GWLP_USERDATA,
PtrToUlong(pReceiver));
T *pOldDoc = (T*)(LONG_PTR)(lptr);
return pOldDoc;
}
template<class T>
LRESULT CALLBACK WindowsProcEx(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
T* pDoc = GetWindowDocument<T>(hWnd);
BOOL bHandled = false;
LRESULT r = Details::SendMessageTo(pDoc, hWnd , message, wParam, lParam, bHandled);
if (bHandled)
{
return r;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
inline bool IsControlKeyPressed()
{
return (GetKeyState(VK_CONTROL) & 0xf000) == 0xf000;
}
inline bool IsShiftKeyPressed()
{
return (GetKeyState(VK_SHIFT) & 0xf000) == 0xf000;
}
#ifndef GET_X_LPARAM
#define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
#endif
#ifndef GET_Y_LPARAM
#define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
#endif
namespace Details
{
class MemoryDC
{
public:
HDC m_hDC;
HDC m_hDCOriginal;
RECT m_rcPaint;
HBITMAP m_hBitmap;
HBITMAP m_hBmpOld;
MemoryDC(HDC hDC, RECT& rcPaint) : m_hDCOriginal(hDC), m_hBmpOld(NULL)
{
m_rcPaint = rcPaint;
m_hDC = ::CreateCompatibleDC(m_hDCOriginal);
ASSERT(m_hDC != NULL);
m_hBitmap = ::CreateCompatibleBitmap(m_hDCOriginal,
m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top);
ASSERT(m_hBitmap != NULL);
m_hBmpOld = (HBITMAP)::SelectObject(m_hDC, m_hBitmap);
::SetViewportOrgEx(m_hDC, -m_rcPaint.left, -m_rcPaint.top, 0);
}
~MemoryDC()
{
::BitBlt(m_hDCOriginal, m_rcPaint.left, m_rcPaint.top,
m_rcPaint.right - m_rcPaint.left, m_rcPaint.bottom - m_rcPaint.top,
m_hDC, m_rcPaint.left, m_rcPaint.top, SRCCOPY);
(HBITMAP)::SelectObject(m_hDC, m_hBmpOld);
::DeleteObject(m_hBitmap);
::DeleteObject(m_hDC);
}
};
template<class TEventReceiver>
LRESULT SendMessageTo(TEventReceiver* pEventReceiver,
HWND hWnd,
UINT uMsg,
WPARAM wparam,
LPARAM lparam,
BOOL& bHandled)
{
bHandled = FALSE;
if (pEventReceiver == NULL)
{
return FALSE;
}
bHandled = TRUE;
switch (uMsg)
{
//notifications
case WM_COMMAND:
case WM_NOTIFY:
{
LRESULT lresult;
pEventReceiver->ProcessWindowMessage(hWnd, uMsg, wparam, lparam, lresult);
}
break;
__if_exists(TEventReceiver::OnDeactivate)
{
case WM_ACTIVATE:
{
if (LOWORD(wparam) == WA_INACTIVE)
{
pEventReceiver->OnDeactivate();
}
break;
}
} //OnDeactivate
#ifndef _WIN32_WCE
__if_exists(TEventReceiver::OnMouseWheel)
{
case WM_MOUSEWHEEL:
{
int fwKeys = GET_KEYSTATE_WPARAM(wparam );
short zDelta = GET_WHEEL_DELTA_WPARAM(wparam );
pEventReceiver->OnMouseWheel(fwKeys, zDelta);
}
break;
}//OnMouseWheel
#endif
__if_exists(TEventReceiver::OnSetFocus)
{
case WM_SETFOCUS:
{
pEventReceiver->OnSetFocus();
}
break;
}
__if_exists(TEventReceiver::OnSetCursor)
{
case WM_SETCURSOR:
{
if (!pEventReceiver->OnSetCursor())
{
bHandled = FALSE;
}
}
break;
}
__if_exists (TEventReceiver::OnKillFocus)
{
case WM_KILLFOCUS:
{
pEventReceiver->OnKillFocus();
}
break;
}//OnKillFocus
__if_exists (TEventReceiver::OnPaint)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
pEventReceiver->OnPaint(hDC);
EndPaint(hWnd, &ps);
}
break;
}
default:
bHandled = FALSE;
return FALSE;
}
return TRUE;
}
} //namespace details
int RunMessageLoop()
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
DWORD GetStyle(HWND m_hWnd)
{
ASSERT(::IsWindow(m_hWnd));
return (DWORD)::GetWindowLong(m_hWnd, GWL_STYLE);
}
BOOL CenterWindow(HWND m_hWnd, HWND hWndCenter = NULL)
{
ASSERT(::IsWindow(m_hWnd));
// determine owner window to center against
DWORD dwStyle = GetStyle(m_hWnd);
if(hWndCenter == NULL)
{
if(dwStyle & WS_CHILD)
hWndCenter = ::GetParent(m_hWnd);
else
hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
}
// get coordinates of the window relative to its parent
RECT rcDlg;
::GetWindowRect(m_hWnd, &rcDlg);
RECT rcArea;
RECT rcCenter;
HWND hWndParent;
if(!(dwStyle & WS_CHILD))
{
// don't center against invisible or minimized windows
if(hWndCenter != NULL)
{
DWORD dwStyleCenter = ::GetWindowLong(hWndCenter, GWL_STYLE);
if(!(dwStyleCenter & WS_VISIBLE) || (dwStyleCenter & WS_MINIMIZE))
hWndCenter = NULL;
}
// center within screen coordinates
#if WINVER < 0x0500
::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);
#else
HMONITOR hMonitor = NULL;
if(hWndCenter != NULL)
{
hMonitor = ::MonitorFromWindow(hWndCenter,
MONITOR_DEFAULTTONEAREST);
}
else
{
hMonitor = ::MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
}
//ATLENSURE_RETURN_VAL(hMonitor != NULL, FALSE);
MONITORINFO minfo;
minfo.cbSize = sizeof(MONITORINFO);
BOOL bResult = ::GetMonitorInfo(hMonitor, &minfo);
//ATLENSURE_RETURN_VAL(bResult, FALSE);
rcArea = minfo.rcWork;
#endif
if(hWndCenter == NULL)
rcCenter = rcArea;
else
::GetWindowRect(hWndCenter, &rcCenter);
}
else
{
// center within parent client coordinates
hWndParent = ::GetParent(m_hWnd);
ASSERT(::IsWindow(hWndParent));
::GetClientRect(hWndParent, &rcArea);
ASSERT(::IsWindow(hWndCenter));
::GetClientRect(hWndCenter, &rcCenter);
::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
}
int DlgWidth = rcDlg.right - rcDlg.left;
int DlgHeight = rcDlg.bottom - rcDlg.top;
// find dialog's upper left based on rcCenter
int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
// if the dialog is outside the screen, move it inside
if(xLeft + DlgWidth > rcArea.right)
xLeft = rcArea.right - DlgWidth;
if(xLeft < rcArea.left)
xLeft = rcArea.left;
if(yTop + DlgHeight > rcArea.bottom)
yTop = rcArea.bottom - DlgHeight;
if(yTop < rcArea.top)
yTop = rcArea.top;
// map screen coordinates to child coordinates
return ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
// Message handler for about box.
template<class T>
INT_PTR CALLBACK DlgProc(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
BOOL bHandled = FALSE;
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
{
T * p = (T*)lParam;
SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR) p);
p->InitEntry(hDlg);
return (INT_PTR)TRUE;
}
}
//TODO : all messages?
T * p = (T*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
LRESULT r = Details::SendMessageTo(p, hDlg, message, wParam, lParam, bHandled);
return bHandled;
}
template<class T>
INT_PTR ShowDialog(LPCWSTR lpTemplateName, T * p, HWND hWndParent)
{
HINSTANCE hInst = GetModuleHandle(NULL);
INT_PTR r = DialogBoxParam(hInst, lpTemplateName, hWndParent, &DlgProc<T>,(LPARAM) p);
ASSERT(r != 0); //resource exists? (1813)
return r;
}
template<class T>
HWND ShowModeless(UINT IDD, T* p, HWND hParent)
{
HWND hWnd = NULL;
HINSTANCE hInstance = GetModuleHandle(NULL);
HRSRC hDlg = FindResource(hInstance, MAKEINTRESOURCE(IDD), RT_DIALOG);
if (hDlg != NULL)
{
DWORD dwLastError = 0;
HGLOBAL hResource = LoadResource(hInstance, hDlg);
if (hResource != NULL)
{
DLGTEMPLATE* pDlg = (DLGTEMPLATE*) LockResource(hResource);
if (pDlg != NULL)
{
hWnd = CreateDialogIndirectParam(
hInstance,
pDlg,
hParent,
&DlgProc<T>,
(LPARAM)p);
UnlockResource(hResource);
}
else
dwLastError = ::GetLastError();
}
else
dwLastError = ::GetLastError();
if (dwLastError != 0)
SetLastError(dwLastError);
}
return hWnd;
}
template<class T, UINT IDD>
class Dialog
{
protected:
HWND m_hDlg;
HWND m_hParent;
public:
int EndDialog(int r)
{
return ::EndDialog(m_hDlg, r);
}
UINT GetDlgItemText(int nID, std::wstring& s) const
{
ASSERT(::IsWindow(m_hDlg));
HWND hItem = GetDlgItem(nID);
if (hItem != NULL)
{
int nLength = ::GetWindowTextLength(hItem);
std::vector<wchar_t> buffer(nLength+1);
wchar_t* pszText = &buffer[0];
nLength = ::GetWindowText(hItem, pszText, nLength+1);
s = pszText;
return nLength;
}
else
{
s.clear();
return 0;
}
}
HWND GetDlgItem(UINT id) const
{
return ::GetDlgItem(m_hDlg, id);
}
Dialog(HWND hParent = NULL) : m_hParent(hParent)
{
}
//WM_INITDIALOG
void InitEntry(HWND hDlg)
{
m_hDlg = hDlg;
CenterWindow(m_hDlg, m_hParent);
__if_exists (T::InitDialog)
{
static_cast<T*>(this)->InitDialog();
}
}
//show modeless
void Show()
{
m_hDlg = ShowModeless(IDD, this, m_hParent);
}
//show modal
int ShowDialog()
{
return ::ShowDialog(MAKEINTRESOURCE(IDD), static_cast<T*>(this), m_hParent);
}
};
template<class T,
UINT IconId =0,
UINT MENUIDD = 0,
UINT wStyle = WS_OVERLAPPEDWINDOW | CS_DBLCLKS
>
class Window
{
protected:
HWND m_hWnd;
public:
static const WNDCLASSEX * GetClass()
{
HINSTANCE hInstance = GetModuleHandle(NULL);
static WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = &WindowsProcEx<T>;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IconId));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
if (MENUIDD != NULL)
wcex.lpszMenuName = MAKEINTRESOURCE(MENUIDD);
else
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"class";
wcex.hIconSm = 0;//LoadIcon(wcex.hInstance,MAKEINTRESOURCE(IDI_SMALL));
return &wcex;
}
Window() : m_hWnd(NULL)
{
}
void Create(HWND hWndParent = 0)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
RegisterClassEx(GetClass());
m_hWnd = CreateWindow(GetClass()->lpszClassName, L"", wStyle,
0, 0, CW_USEDEFAULT, CW_USEDEFAULT, hWndParent, NULL, hInstance, NULL);
SetWindowDocument(m_hWnd, static_cast<T*>(this));
ShowWindow(m_hWnd, TRUE);
UpdateWindow(m_hWnd);
}
};
#if defined _M_IX86
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#define COMMAND_ID_HANDLER(id, func) \
if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
{ \
bHandled = TRUE; \
lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define S_COMMAND_ID_HANDLER(id, func) \
if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
{ \
bHandled = TRUE; \
lResult = 1;\
bHandled = TRUE;\
func(); \
if(bHandled) \
return TRUE; \
}
#define COMMAND_HANDLER(id, code, func) \
if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
{ \
bHandled = TRUE; \
lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define BEGIN_MSG_MAP(theClass) \
public: \
BOOL ProcessWindowMessage(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam,\
_In_ LPARAM lParam, _Inout_ LRESULT& lResult, _In_ DWORD dwMsgMapID = 0) \
{ \
BOOL bHandled = TRUE; \
(hWnd); \
(uMsg); \
(wParam); \
(lParam); \
(lResult); \
(bHandled); \
switch(dwMsgMapID) \
{ \
case 0:
#define END_MSG_MAP() \
break; \
default: \
break; \
} \
return FALSE; \
}