/*
* Copyright (c) 2015 akamoz.jp
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <windows.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <assert.h>
class Window {
public:
Window(HWND hwnd = NULL) { set(hwnd); }
HWND create(LPCTSTR cls, DWORD ws, DWORD exws, HWND parent = NULL,
LPCTSTR title = TEXT(""), HMENU hmenu = NULL,
LPVOID lpv = NULL, int xpos = CW_USEDEFAULT, int ypos = 0,
int width = 100, int height = 70) {
if ((width == (int)CW_USEDEFAULT) && (ws & WS_CHILD)) {
width = 100;
height = 100;
}
mhwnd = ::CreateWindowEx(exws, cls, title, ws,
xpos, ypos, width, height, parent, hmenu,
GetModuleHandle(NULL), lpv);
return mhwnd;
}
BOOL destroy() {
return ::DestroyWindow(mhwnd);
}
HWND get() { return mhwnd; }
void set(HWND hwnd) { mhwnd = hwnd; }
LONG_PTR setLongPtr(int nIndex, LONG_PTR nVal) {
return ::SetWindowLongPtr(mhwnd, nIndex, nVal);
}
LONG_PTR getLongPtr(int nIndex) {
return ::GetWindowLongPtr(mhwnd, nIndex);
}
LRESULT defproc(UINT u, WPARAM w, LPARAM l) {
return ::DefWindowProc(mhwnd, u, w, l);
}
LRESULT postMessage(UINT uMsg, WPARAM wp = 0, LPARAM lp = 0) {
return ::PostMessage(mhwnd, uMsg, wp, lp);
}
BOOL show(int n = SW_SHOW) {
return ::ShowWindow(mhwnd, n);
}
private:
HWND mhwnd;
};
class WindowBase : public virtual Window {
public:
WindowBase();
virtual ~WindowBase();
HWND create(
HWND hwndParent, DWORD ws, DWORD exws = 0,
LPCTSTR title=TEXT(""), HMENU hmenu = (0)
);
ATOM registerClass();
protected:
LPCTSTR mptszClass;
virtual LRESULT wndproc(UINT uMsg, WPARAM wp, LPARAM lp);
private:
static LRESULT CALLBACK _wndproc(HWND, UINT, WPARAM, LPARAM);
};
WindowBase::WindowBase()
{
}
WindowBase::~WindowBase()
{
if (get() != NULL)
destroy();
}
LRESULT CALLBACK WindowBase::_wndproc(
HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp
) {
WindowBase *pwnd;
pwnd = (WindowBase *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if ((pwnd == NULL) && (uMsg == WM_NCCREATE)) {
CREATESTRUCT *pcs = (CREATESTRUCT *)lp;
pwnd = (WindowBase *)pcs->lpCreateParams;
if (pwnd != NULL) {
pwnd->set(hwnd);
pwnd->setLongPtr(GWLP_USERDATA, (LONG_PTR)pwnd);
}
}
if (pwnd != NULL) {
assert(pwnd->get() == hwnd);
return pwnd->wndproc(uMsg, wp, lp);
}
return ::DefWindowProc(hwnd, uMsg, wp, lp);
}
LRESULT WindowBase::wndproc(UINT uMsg, WPARAM wp, LPARAM lp)
{
return defproc(uMsg, wp, lp);
}
#define WINDOWCLASSNAME TEXT("akamoz.jp/WindowBase")
ATOM WindowBase::registerClass()
{
LPCTSTR pszClass = WINDOWCLASSNAME;
ATOM atm = FindAtom(pszClass);
if(atm == 0) {
HINSTANCE hinst = GetModuleHandle(NULL);
WNDCLASS wc;
memset(&wc, 0, sizeof(wc));
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = _wndproc;
wc.hInstance = hinst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = pszClass;
atm = RegisterClass(&wc);
}
return atm;
}
HWND WindowBase::create(
HWND hwndParent, DWORD ws, DWORD exws, LPCTSTR title, HMENU hmenu
) {
if (registerClass() == 0)
return NULL;
Window::create(WINDOWCLASSNAME, ws, exws, hwndParent, title, hmenu, this);
return get();
}
class Message : public MSG {
public:
BOOL get(HWND hwnd = NULL, UINT uMin = 0, UINT uMax = 0) {
return ::GetMessage(this, hwnd, uMin, uMax);
}
BOOL peek(
UINT flag = PM_REMOVE, HWND hwnd = NULL, UINT uMin = 0, UINT uMax = 0
) {
return ::PeekMessage(this, hwnd, uMin, uMax, flag);
}
BOOL translate() {
return ::TranslateMessage(this);
}
LONG dispatch() {
return ::DispatchMessage(this);
}
WPARAM doLoop();
};
WPARAM Message::doLoop()
{
while (get()) {
translate();
dispatch();
}
return wParam;
}
class Win32Timer {
public:
Win32Timer() {
muID = 0;
mhwnd = NULL;
}
~Win32Timer() {
kill();
}
int set(HWND hwnd, UINT_PTR uID, UINT umsec, TIMERPROC proc = NULL) {
muID = ::SetTimer(hwnd, uID, umsec, proc);
if (muID == 0)
return -1;
mhwnd = hwnd;
if (hwnd != NULL)
muID = uID;
return 0;
}
int kill() {
if (muID == 0)
return 0;
if (::KillTimer(mhwnd, muID) == FALSE)
return -1;
muID = 0;
return 0;
}
private:
UINT_PTR muID;
HWND mhwnd;
};
class MainWindow : public WindowBase {
protected:
virtual LRESULT wndproc(UINT uMsg, WPARAM wp, LPARAM lp);
private:
Win32Timer tm;
};
LRESULT MainWindow::wndproc(UINT uMsg, WPARAM wp, LPARAM lp)
{
switch (uMsg) {
case WM_CREATE:
tm.set(get(), 1, 100);
return 0;
case WM_TIMER: {
sigset_t sig;
sigpending(&sig);
}
return 0;
case WM_DESTROY:
tm.kill();
PostQuitMessage(0);
return 0;
}
return WindowBase::wndproc(uMsg, wp, lp);
}
MainWindow win;
BOOL WINAPI ctrlHandler(DWORD)
{
fprintf(stderr, "!");
win.postMessage(WM_CLOSE);
return TRUE;
}
void sighandler(int)
{
fprintf(stderr, "#");
win.postMessage(WM_CLOSE);
}
int main(void)
{
SetConsoleCtrlHandler(ctrlHandler, TRUE);
signal(SIGINT, sighandler);
win.create(NULL, WS_OVERLAPPEDWINDOW);
win.show();
Message msg;
msg.doLoop();
getchar();
return 0;
}