home *** CD-ROM | disk | FTP | other *** search
- /*
- Company: Sensaura
- Copyright: (C) 1998
-
- File Name: window.cpp
- File Description: Source file for implementation of Window class
- Author: Adam Philp
- Version: 1.01.000
- Last Update: 01-DEC-98
-
- Target Compiler: Microsoft Visual C++ Version 5.0
- */
-
- /////////////////////// Included files ////////////////////////////////////////////////////////////
-
- #include <windows.h>
- #include <stddef.h>
- #include <string.h>
-
- #include "window.h"
- #include "applicat.h"
- #include "resource.h"
-
- #include "debug.h"
-
- /////////////////////// Local type definitions ////////////////////////////////////////////////////
-
- typedef LRESULT (CALLBACK *ThunkProc)(HWND, UINT, WPARAM, LPARAM);
-
- #pragma pack(1)
-
- struct InstanceThunk
- {
- BYTE Call;
- int Offset;
- ThunkProc Proc;
- Window* Window;
- BYTE Code[6];
- };
- #pragma pack()
-
- /////////////////////// Constants /////////////////////////////////////////////////////////////////
-
- static const int CodeOffset = offsetof(InstanceThunk, Code)-offsetof(InstanceThunk, Proc);
-
- /////////////////////// Local variables ///////////////////////////////////////////////////////////
-
- Window* g_ThunkWindow = NULL;
-
- /////////////////////// Local functions ///////////////////////////////////////////////////////////
-
- /*
- The following functions handle setting the pThunk for our window object to enable us to use a
- C++ class to handle Windows messages
- */
-
- WNDPROC CreateInstanceThunk(Window* w, ThunkProc thunkProc)
- {
- InstanceThunk* pThunk;
-
- pThunk = new InstanceThunk;
-
- pThunk->Call = 0xE8u; // CALL rel32
- pThunk->Offset = CodeOffset; // relative displacement to Code[5]
- pThunk->Proc = thunkProc;
- pThunk->Window = w;
-
- // POP ECX
- //
- // pop return address of call into ecx (address of member "Proc")
- //
- pThunk->Code[0] = 0x59u;
-
- // MOV EAX,[ECX+4]
- //
- // load "Window" into ebx
- //
- pThunk->Code[1] = 0x8Bu; // MOV r32,r/m32
- pThunk->Code[2] = 0x41u; // eax,disp8[ECX]
- pThunk->Code[3] = 0x04u; // +4
-
- // JMP [ECX]
- //
- // jump to window function provided
- //
- pThunk->Code[4] = 0xFFu; // JMP r/m32
- pThunk->Code[5] = 0x21u; // [ECX]
-
- return (WNDPROC)pThunk;
- }
-
- void FreeInstanceThunk(WNDPROC proc)
- {
- delete (InstanceThunk*)proc;
- }
-
- void SetWindowToThunk(Window* w)
- {
- g_ThunkWindow = w;
- }
-
- Window* GetWindowToThunk()
- {
- return g_ThunkWindow;
- }
-
- LRESULT CALLBACK InitWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- WNDPROC pThunk;
-
- if(!g_ThunkWindow)
- return DefWindowProc(hwnd, message, wParam, lParam);
- g_ThunkWindow->m_hWnd = hwnd;
- g_ThunkWindow->SetDefaultProc((WNDPROC)GetProcAddress((HINSTANCE)GetModuleHandle("USER32"),
- "DefWindowProcA"));
- pThunk = g_ThunkWindow->GetThunk();
- g_ThunkWindow = NULL;
-
- ::SetWindowLong(hwnd, GWL_WNDPROC, (long)pThunk);
- return (*(WNDPROC)(pThunk))(hwnd, message, wParam, lParam);
- }
-
- /////////////////////// Window class implementation ///////////////////////////////////////////////
-
- Window::Window(Window* pParent, LPCSTR pCaption, Application* pApp)
- {
- m_pParent = pParent;
- m_pCaption = strdup(pCaption);
- m_pApp = pApp;
-
- m_hWnd = NULL;
-
- m_Attr.dwExStyle = 0;
- m_Attr.dwStyle = WS_OVERLAPPEDWINDOW;
- m_Attr.X = CW_USEDEFAULT;
- m_Attr.Y = CW_USEDEFAULT;
- m_Attr.W = CW_USEDEFAULT;
- m_Attr.H = CW_USEDEFAULT;
- m_Attr.hMenu = NULL;
- m_Attr.hIcon = NULL;
-
- m_DefaultProc = NULL;
- m_Thunk = CreateInstanceThunk(this, StdWndProc);
- }
-
- Window::~Window()
- {
- DestroyWindow();
-
- if(m_pCaption)
- delete m_pCaption;
-
- FreeInstanceThunk(m_Thunk);
- }
-
- /////////////////////// Window public member functions ////////////////////////////////////////////
-
- int Window::GetClassName(LPSTR className, int maxCount) const
- {
- return ::GetClassName(m_hWnd, className, maxCount);
- }
-
- LPSTR Window::GetClassName() const
- {
- return "Window";
- }
-
- void Window::GetWindowClass(WNDCLASS& wc) const
- {
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = m_pApp->GetInstance();
- wc.hIcon = m_Attr.hIcon;
- wc.hCursor = ::LoadCursor(0, IDC_ARROW);
-
- wc.hbrBackground = HBRUSH(COLOR_WINDOW+1);
-
- wc.lpszMenuName = 0;
- wc.lpszClassName = GetClassName();
- wc.style = CS_DBLCLKS;
- wc.lpfnWndProc = InitWndProc;
- }
-
- bool Window::Create()
- {
- if(Register())
- {
- SetWindowToThunk(this);
-
- m_hWnd = CreateWindowEx(m_Attr.dwExStyle,
- GetClassName(),
- m_pCaption,
- m_Attr.dwStyle,
- m_Attr.X, m_Attr.Y, m_Attr.W, m_Attr.H,
- m_pParent ? m_pParent->m_hWnd : NULL,
- m_Attr.hMenu,
- m_pApp->GetInstance(),
- NULL );
- }
- if(GetWindowToThunk() == this)
- SetWindowToThunk(NULL);
- if(m_hWnd == NULL)
- return false;
-
- return true;
- }
-
- bool Window::ShowWindow(int nCmdShow)
- {
- if(m_hWnd)
- return ::ShowWindow(m_hWnd, nCmdShow) ? true : false;
- return false;
- }
-
- LRESULT Window::EvCommand(UINT id, HWND hwndCtl, UINT notifyCode)
- {
- if(id == CM_EXIT)
- SendMessage(WM_CLOSE);
-
- return 0;
- }
-
- bool Window::IdleAction(long idleCount)
- {
- return false;
- }
-
- int Window::MessageBox(LPCSTR message, LPCSTR pCaption, UINT uStyle) const
- {
- return ::MessageBox(m_hWnd, message, pCaption, uStyle);
- }
-
- /////////////////////// Window protected member functions /////////////////////////////////////////
-
- bool Window::Register()
- {
- WNDCLASS wc;
-
- if(!GetClassInfo(m_pApp->GetInstance(), GetClassName(), &wc))
- {
- GetWindowClass(wc);
- return ::RegisterClass(&wc) ? true : false;
- }
- return true;
- }
-
- void Window::DestroyWindow(int)
- {
- if (m_hWnd)
- ::DestroyWindow(m_hWnd);
- }
-
- void Window::CloseWindow(int ret)
- {
- DestroyWindow(ret);
- }
-
- LRESULT Window::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch(message)
- {
- case WM_COMMAND:
- return EvCommand((UINT)LOWORD (wParam), (HWND)LOWORD (lParam), (UINT) HIWORD(wParam));
-
- case WM_PAINT:
- EvPaint();
- return 0;
-
- case WM_DESTROY:
- EvDestroy();
- break;
-
- case WM_CLOSE:
- EvClose();
- return 0;
- }
- return DefWindowProc(m_hWnd, message, wParam, lParam);
- }
-
- void Window::EvPaint()
- {
- PAINTSTRUCT ps;
-
- BeginPaint(m_hWnd, &ps);
- Paint(ps.hdc, ps.rcPaint, ps.fErase ? true : false);
- EndPaint(m_hWnd, &ps);
- }
-
- void Window::EvClose()
- {
- CloseWindow();
- }
-
- void Window::EvDestroy()
- {
- if(m_pApp)
- if(m_pApp->GetMainWindow() == this)
- PostQuitMessage(0);
-
- m_hWnd = NULL;
- }
-
- /////////////////////// Window private member functions ///////////////////////////////////////////
-
- void Window::InstallWindowProc()
- {
- DWORD processId;
-
- if(m_hWnd)
- {
- GetWindowThreadProcessId(m_hWnd, &processId);
- if(processId == GetCurrentProcessId())
- m_DefaultProc = (WNDPROC)SetWindowLong(m_hWnd, GWL_WNDPROC, (long)GetThunk());
- }
- }
-
- LRESULT CALLBACK Window::StdWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- Window* w;
-
- _asm mov w, eax
- return w->WindowProc(message, wParam, lParam);
- }
-