home *** CD-ROM | disk | FTP | other *** search
/ Game Audio Programming / GameAudioProgramming.iso / Extras / Sensaura / SDK1.0 / data1.cab / Example_Files / DS3DDemo / Source / window.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-13  |  6.9 KB  |  324 lines

  1. /*
  2.     Company:            Sensaura
  3.     Copyright:          (C) 1998
  4.  
  5.     File Name:            window.cpp
  6.     File Description:    Source file for implementation of Window class
  7.     Author:                Adam Philp
  8.     Version:            1.01.000
  9.     Last Update:        01-DEC-98
  10.  
  11.     Target Compiler:    Microsoft Visual C++ Version 5.0
  12. */
  13.  
  14. ///////////////////////    Included files ////////////////////////////////////////////////////////////
  15.  
  16. #include <windows.h>
  17. #include <stddef.h>
  18. #include <string.h>
  19.  
  20. #include "window.h"
  21. #include "applicat.h"
  22. #include "resource.h"
  23.  
  24. #include "debug.h"
  25.  
  26. ///////////////////////    Local type definitions ////////////////////////////////////////////////////
  27.  
  28. typedef LRESULT (CALLBACK *ThunkProc)(HWND, UINT, WPARAM, LPARAM);
  29.  
  30. #pragma pack(1)
  31.  
  32. struct InstanceThunk 
  33. {
  34.   BYTE        Call;
  35.   int        Offset;
  36.   ThunkProc    Proc;
  37.   Window*    Window;
  38.   BYTE        Code[6];
  39. };
  40. #pragma pack()
  41.  
  42. ///////////////////////    Constants /////////////////////////////////////////////////////////////////
  43.  
  44. static const int CodeOffset = offsetof(InstanceThunk, Code)-offsetof(InstanceThunk, Proc);
  45.  
  46. ///////////////////////    Local variables ///////////////////////////////////////////////////////////
  47.  
  48. Window* g_ThunkWindow = NULL;
  49.  
  50. ///////////////////////    Local functions ///////////////////////////////////////////////////////////
  51.  
  52. /*
  53.     The following functions handle setting the pThunk for our window object to enable us to use a
  54.     C++ class to handle Windows messages
  55. */
  56.  
  57. WNDPROC CreateInstanceThunk(Window* w, ThunkProc thunkProc)
  58. {
  59.   InstanceThunk* pThunk;
  60.   
  61.   pThunk = new InstanceThunk;
  62.  
  63.   pThunk->Call = 0xE8u;        // CALL rel32
  64.   pThunk->Offset = CodeOffset; // relative displacement to Code[5]
  65.   pThunk->Proc = thunkProc;
  66.   pThunk->Window = w;
  67.  
  68.   // POP ECX
  69.   //
  70.   // pop return address of call into ecx (address of member "Proc")
  71.   //
  72.   pThunk->Code[0] = 0x59u;
  73.  
  74.   // MOV EAX,[ECX+4]
  75.   //
  76.   // load "Window" into ebx
  77.   //
  78.   pThunk->Code[1] = 0x8Bu;     // MOV r32,r/m32
  79.   pThunk->Code[2] = 0x41u;     // eax,disp8[ECX]
  80.   pThunk->Code[3] = 0x04u;     // +4
  81.  
  82.   // JMP [ECX]
  83.   //
  84.   // jump to window function provided
  85.   //
  86.   pThunk->Code[4] = 0xFFu;     // JMP r/m32
  87.   pThunk->Code[5] = 0x21u;     // [ECX]
  88.  
  89.   return (WNDPROC)pThunk;
  90. }
  91.  
  92. void FreeInstanceThunk(WNDPROC proc)
  93. {
  94.   delete (InstanceThunk*)proc;
  95. }
  96.  
  97. void SetWindowToThunk(Window* w)
  98. {
  99.     g_ThunkWindow = w;
  100. }
  101.  
  102. Window* GetWindowToThunk()
  103. {
  104.     return g_ThunkWindow;
  105. }
  106.  
  107. LRESULT    CALLBACK InitWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  108. {
  109.     WNDPROC pThunk;
  110.  
  111.     if(!g_ThunkWindow)
  112.         return DefWindowProc(hwnd, message, wParam, lParam);
  113.     g_ThunkWindow->m_hWnd = hwnd;
  114.     g_ThunkWindow->SetDefaultProc((WNDPROC)GetProcAddress((HINSTANCE)GetModuleHandle("USER32"), 
  115.                                                           "DefWindowProcA"));
  116.     pThunk = g_ThunkWindow->GetThunk();
  117.     g_ThunkWindow = NULL;
  118.  
  119.     ::SetWindowLong(hwnd, GWL_WNDPROC, (long)pThunk);
  120.     return (*(WNDPROC)(pThunk))(hwnd, message, wParam, lParam);
  121. }
  122.  
  123. /////////////////////// Window class implementation ///////////////////////////////////////////////
  124.  
  125. Window::Window(Window* pParent, LPCSTR pCaption, Application* pApp)
  126. {
  127.     m_pParent = pParent;
  128.     m_pCaption = strdup(pCaption);
  129.     m_pApp = pApp;
  130.  
  131.     m_hWnd = NULL;
  132.  
  133.     m_Attr.dwExStyle = 0;
  134.     m_Attr.dwStyle = WS_OVERLAPPEDWINDOW;
  135.     m_Attr.X = CW_USEDEFAULT;
  136.     m_Attr.Y = CW_USEDEFAULT;
  137.     m_Attr.W = CW_USEDEFAULT;
  138.     m_Attr.H = CW_USEDEFAULT;
  139.     m_Attr.hMenu = NULL;
  140.     m_Attr.hIcon = NULL;
  141.  
  142.     m_DefaultProc = NULL;
  143.     m_Thunk = CreateInstanceThunk(this, StdWndProc);
  144. }
  145.  
  146. Window::~Window()
  147. {
  148.     DestroyWindow();
  149.  
  150.     if(m_pCaption)
  151.         delete m_pCaption;
  152.     
  153.     FreeInstanceThunk(m_Thunk);
  154. }
  155.  
  156. /////////////////////// Window public member functions ////////////////////////////////////////////
  157.  
  158. int Window::GetClassName(LPSTR className, int maxCount) const
  159. {
  160.     return ::GetClassName(m_hWnd, className, maxCount);
  161. }
  162.  
  163. LPSTR Window::GetClassName() const
  164. {
  165.     return "Window";
  166. }
  167.  
  168. void Window::GetWindowClass(WNDCLASS& wc) const
  169. {
  170.     wc.cbClsExtra = 0;
  171.     wc.cbWndExtra = 0;
  172.     wc.hInstance = m_pApp->GetInstance();
  173.     wc.hIcon = m_Attr.hIcon;
  174.     wc.hCursor = ::LoadCursor(0, IDC_ARROW);
  175.  
  176.     wc.hbrBackground = HBRUSH(COLOR_WINDOW+1);
  177.  
  178.     wc.lpszMenuName = 0;
  179.     wc.lpszClassName = GetClassName();
  180.     wc.style = CS_DBLCLKS;
  181.     wc.lpfnWndProc = InitWndProc;
  182. }
  183.  
  184. bool Window::Create()
  185. {
  186.     if(Register()) 
  187.     {
  188.         SetWindowToThunk(this);
  189.  
  190.         m_hWnd = CreateWindowEx(m_Attr.dwExStyle,
  191.                                 GetClassName(),
  192.                                 m_pCaption,
  193.                                 m_Attr.dwStyle,
  194.                                 m_Attr.X, m_Attr.Y, m_Attr.W, m_Attr.H,      
  195.                                 m_pParent ? m_pParent->m_hWnd : NULL, 
  196.                                 m_Attr.hMenu,              
  197.                                 m_pApp->GetInstance(), 
  198.                                 NULL );
  199.     }
  200.     if(GetWindowToThunk() == this)
  201.         SetWindowToThunk(NULL);
  202.     if(m_hWnd == NULL)
  203.         return false;
  204.  
  205.     return true;
  206. }
  207.  
  208. bool Window::ShowWindow(int nCmdShow)
  209. {
  210.     if(m_hWnd)
  211.         return ::ShowWindow(m_hWnd, nCmdShow) ? true : false;
  212.     return false;
  213. }
  214.  
  215. LRESULT Window::EvCommand(UINT id, HWND hwndCtl, UINT notifyCode)
  216. {
  217.     if(id == CM_EXIT) 
  218.         SendMessage(WM_CLOSE);
  219.  
  220.     return 0;
  221. }
  222.  
  223. bool Window::IdleAction(long idleCount)
  224. {
  225.     return false;
  226. }
  227.  
  228. int    Window::MessageBox(LPCSTR message, LPCSTR pCaption, UINT uStyle) const
  229. {
  230.     return ::MessageBox(m_hWnd, message, pCaption, uStyle);
  231. }
  232.  
  233. /////////////////////// Window protected member functions /////////////////////////////////////////
  234.  
  235. bool Window::Register()
  236. {
  237.     WNDCLASS wc;
  238.  
  239.     if(!GetClassInfo(m_pApp->GetInstance(), GetClassName(), &wc)) 
  240.     {
  241.         GetWindowClass(wc);
  242.         return ::RegisterClass(&wc) ? true : false;
  243.     }
  244.     return true;
  245. }
  246.  
  247. void Window::DestroyWindow(int)
  248. {
  249.     if (m_hWnd) 
  250.         ::DestroyWindow(m_hWnd);
  251. }
  252.  
  253. void Window::CloseWindow(int ret)
  254. {
  255.     DestroyWindow(ret);
  256. }
  257.  
  258. LRESULT Window::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  259. {
  260.     switch(message) 
  261.     {
  262.     case WM_COMMAND:
  263.         return EvCommand((UINT)LOWORD (wParam), (HWND)LOWORD (lParam), (UINT) HIWORD(wParam));
  264.     
  265.     case WM_PAINT:
  266.         EvPaint();
  267.         return 0;
  268.  
  269.     case WM_DESTROY:
  270.         EvDestroy();
  271.         break;
  272.  
  273.     case WM_CLOSE:
  274.         EvClose();
  275.         return 0;
  276.     }
  277.     return DefWindowProc(m_hWnd, message, wParam, lParam);
  278. }
  279.  
  280. void Window::EvPaint()
  281. {
  282.     PAINTSTRUCT    ps;
  283.     
  284.     BeginPaint(m_hWnd, &ps);
  285.     Paint(ps.hdc, ps.rcPaint, ps.fErase ? true : false);
  286.     EndPaint(m_hWnd, &ps);
  287. }
  288.  
  289. void Window::EvClose()
  290. {
  291.     CloseWindow();
  292. }
  293.  
  294. void Window::EvDestroy()
  295. {
  296.     if(m_pApp)
  297.         if(m_pApp->GetMainWindow() == this)
  298.             PostQuitMessage(0);
  299.  
  300.     m_hWnd = NULL;
  301. }
  302.  
  303. /////////////////////// Window private member functions ///////////////////////////////////////////
  304.  
  305. void Window::InstallWindowProc()
  306. {
  307.     DWORD processId;
  308.  
  309.     if(m_hWnd) 
  310.     {
  311.         GetWindowThreadProcessId(m_hWnd, &processId);
  312.         if(processId == GetCurrentProcessId()) 
  313.             m_DefaultProc = (WNDPROC)SetWindowLong(m_hWnd, GWL_WNDPROC, (long)GetThunk());
  314.     }
  315. }
  316.  
  317. LRESULT    CALLBACK Window::StdWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  318. {
  319.     Window* w;
  320.  
  321.     _asm mov w, eax
  322.     return w->WindowProc(message, wParam, lParam);
  323. }
  324.