/* * 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; }