CPI_Interface.c
上传用户:hxb_1234
上传日期:2010-03-30
资源大小:8328k
文件大小:28k
源码类别:

VC书籍

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////////////////////
  2. #include "stdafx.h"
  3. #include "globals.h"
  4. #include "resource.h"
  5. #include "WindowsOS.h"
  6. #include "CPI_InterfacePart.h"
  7. ////////////////////////////////////////////////////////////////////////////////
  8. // Handy macro to tidy up the source (handles the "SetHandler_xxxx" functions)
  9. #define CPC_IMPLEMENT_SETHANDLER(handlertype)
  10. void IF_sethandler_##handlertype(CP_HINTERFACE hInterface, wp_IF_##handlertype pfnHandler) {
  11. CPs_InterfaceWindowState* pState;
  12. pState = (CPs_InterfaceWindowState*)hInterface;
  13. CP_CHECKOBJECT(pState);
  14. pState->m_hndlr_##handlertype = pfnHandler; }
  15. //
  16. ////////////////////////////////////////////////////////////////////////////////
  17. #define CPC_SIZEBORDER 0x4
  18. ////////////////////////////////////////////////////////////////////////////////
  19. //
  20. typedef struct _CPs_InterfaceWindowState
  21. {
  22.     HWND m_hWnd;
  23.     DWORD m_dwStyle;
  24.     SIZE m_szMinSize;
  25.     // Windowpos
  26.     POINT m_ptWindowPos;
  27.     SIZE m_szWindowSize;
  28.     // Window state
  29.     BOOL m_bSkipRegion;
  30.     BOOL m_bMouseLeaveEventSet;
  31.     CPs_InterfacePart* m_pFloatActiveSubpart;
  32.     CPs_InterfacePart* m_pActiveSubpart;
  33.     // Callback handlers
  34.     wp_IF_onCreate m_hndlr_onCreate;
  35.     wp_IF_onDestroy m_hndlr_onDestroy;
  36.     wp_IF_onPosChange m_hndlr_onPosChange;
  37.     wp_IF_onDraw m_hndlr_onDraw;
  38.     wp_IF_onKeyDown m_hndlr_onKeyDown;
  39.     wp_IF_onDropFiles m_hndlr_onDropFiles;
  40.     wp_IF_onFocus m_hndlr_onFocus;
  41.     wp_IF_onAppMessage m_hndlr_onAppMessage;
  42.     wp_IF_onCommandMessage m_hndlr_onCommandMessage;
  43.     wp_IF_onClose m_hndlr_onClose;
  44.     BOOL m_bMouseCaptured;
  45.     wp_IF_onMouseMessage m_hndlr_onMouseMove;
  46.     wp_IF_onMouseMessage m_hndlr_onMouseButton_LUp;
  47.     // Subparts
  48.     CPs_InterfacePart* m_pFirstSubPart;
  49. } CPs_InterfaceWindowState;
  50. //
  51. ////////////////////////////////////////////////////////////////////////////////
  52. LRESULT CALLBACK exp_InterfaceWindowProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam);
  53. void IF_PaintWindow(CPs_InterfaceWindowState* pState, CPs_DrawContext* pContext);
  54. ////////////////////////////////////////////////////////////////////////////////
  55. //
  56. //
  57. //
  58. CPC_IMPLEMENT_SETHANDLER(onCreate)
  59. CPC_IMPLEMENT_SETHANDLER(onDestroy)
  60. CPC_IMPLEMENT_SETHANDLER(onPosChange)
  61. CPC_IMPLEMENT_SETHANDLER(onDraw)
  62. CPC_IMPLEMENT_SETHANDLER(onKeyDown)
  63. CPC_IMPLEMENT_SETHANDLER(onDropFiles)
  64. CPC_IMPLEMENT_SETHANDLER(onFocus)
  65. CPC_IMPLEMENT_SETHANDLER(onAppMessage)
  66. CPC_IMPLEMENT_SETHANDLER(onCommandMessage)
  67. CPC_IMPLEMENT_SETHANDLER(onClose)
  68. //
  69. //
  70. //
  71. HWND IF_GetHWnd(CP_HINTERFACE hInterface)
  72. {
  73.     CPs_InterfaceWindowState* pState;
  74.     // Init
  75.     pState = (CPs_InterfaceWindowState*)hInterface;
  76.     CP_CHECKOBJECT(pState);
  77.     return pState->m_hWnd;
  78. }
  79. //
  80. //
  81. //
  82. void IF_ProcessInit()
  83. {
  84.     WNDCLASS wcPlaylist;
  85.     wcPlaylist.style = 0L;
  86.     wcPlaylist.lpfnWndProc = exp_InterfaceWindowProc;
  87.     wcPlaylist.cbClsExtra = 0;
  88.     wcPlaylist.cbWndExtra = 0;
  89.     wcPlaylist.hInstance = GetModuleHandle(NULL);
  90.     wcPlaylist.hIcon = NULL; // We will explicity set our icons (so that we have a nice small icon)
  91.     wcPlaylist.hCursor = LoadCursor(NULL, IDC_ARROW);
  92.     wcPlaylist.hbrBackground = (HBRUSH)GetStockObject(HOLLOW_BRUSH); // Prevent the system drawing white over our invaid rgn before we can paint
  93.     wcPlaylist.lpszMenuName = NULL;
  94.     wcPlaylist.lpszClassName = CLC_COOLPLAYER_INTERFACECLASSNAME;
  95.     RegisterClass(&wcPlaylist);
  96. }
  97. //
  98. //
  99. //
  100. void IF_ProcessDeInit()
  101. {
  102.     UnregisterClass(CLC_COOLPLAYER_INTERFACECLASSNAME, GetModuleHandle(NULL));
  103. }
  104. //
  105. //
  106. //
  107. CP_HINTERFACE IF_Create(const char* pcTitle, const RECT* pInitialSize, const DWORD dwStyle)
  108. {
  109.     CPs_InterfaceWindowState* pState;
  110.     pState = (CPs_InterfaceWindowState*)malloc(sizeof(*pState));
  111.     memset(pState, 0, sizeof(*pState));
  112.     return pState;
  113. }
  114. //
  115. //
  116. //
  117. void IF_OpenWindow(CP_HINTERFACE hInterface, const char* pcTitle, const RECT* pInitialSize, const DWORD dwStyle)
  118. {
  119.     CPs_InterfaceWindowState* pState;
  120.     // Init
  121.     pState = (CPs_InterfaceWindowState*)hInterface;
  122.     CP_CHECKOBJECT(pState);
  123.     // Setup base state
  124.     pState->m_dwStyle = dwStyle;
  125.     pState->m_bSkipRegion = FALSE;
  126.     // Create Windows window
  127.     CreateWindowEx(WS_EX_ACCEPTFILES,
  128.                    CLC_COOLPLAYER_INTERFACECLASSNAME,
  129.                    pcTitle,
  130.                    WS_POPUP | WS_CLIPCHILDREN | WS_SYSMENU
  131.                    | ((dwStyle & CPC_INTERFACE_STYLE_RESIZING) ? WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME : 0),
  132.                    pInitialSize->left, pInitialSize->top,
  133.                    pInitialSize->right - pInitialSize->left,
  134.                    pInitialSize->bottom - pInitialSize->top,
  135.                    NULL,
  136.                    NULL,
  137.                    GetModuleHandle(NULL),
  138.                    pState);
  139. }
  140. //
  141. //
  142. //
  143. void IF_CleanupState(CPs_InterfaceWindowState* pState)
  144. {
  145.     free(pState);
  146. }
  147. //
  148. //
  149. //
  150. void IF_CloseWindow(CP_HINTERFACE hInterface)
  151. {
  152.     CPs_InterfaceWindowState* pState;
  153.     // Init
  154.     pState = (CPs_InterfaceWindowState*)hInterface;
  155.     CP_CHECKOBJECT(pState);
  156.     DestroyWindow(pState->m_hWnd);
  157. }
  158. //
  159. //
  160. //
  161. void IF_SetVisible(CP_HINTERFACE hInterface, const BOOL bVisible)
  162. {
  163.     CPs_InterfaceWindowState* pState;
  164.     // Init
  165.     pState = (CPs_InterfaceWindowState*)hInterface;
  166.     CP_CHECKOBJECT(pState);
  167.     ShowWindow(pState->m_hWnd, bVisible ? SW_SHOW : SW_HIDE);
  168. }
  169. //
  170. //
  171. //
  172. void IF_SetFloatActiveSubPart(CPs_InterfaceWindowState* pState, CPs_InterfacePart* pNewFloatActiveSubPart)
  173. {
  174.     // If this OS cannot give us mouseleave notification - do not do any float active stuff
  175.     if(!pfnTrackMouseEvent)
  176.         return;
  177.     if(pState->m_pFloatActiveSubpart == pNewFloatActiveSubPart)
  178.         return;
  179.     // Set mouseleave event
  180.     if(pState->m_bMouseLeaveEventSet == FALSE)
  181.     {
  182.         TRACKMOUSEEVENT tme;
  183.         tme.cbSize = sizeof(tme);
  184.         tme.dwFlags = TME_LEAVE;
  185.         tme.hwndTrack = pState->m_hWnd;
  186.         pState->m_bMouseLeaveEventSet = pfnTrackMouseEvent(&tme) ? TRUE : FALSE;
  187.     }
  188.     // Reset existing FA target
  189.     if(pState->m_pFloatActiveSubpart)
  190.     {
  191.         if(pState->m_pFloatActiveSubpart->onMouseOut)
  192.             pState->m_pFloatActiveSubpart->onMouseOut(pState->m_pFloatActiveSubpart);
  193.     }
  194.     // Set new FA target - do not set it if another target has buttondown
  195.     if(pState->m_pActiveSubpart == NULL
  196.             || pNewFloatActiveSubPart == NULL
  197.             || pState->m_pActiveSubpart == pNewFloatActiveSubPart)
  198.     {
  199.         pState->m_pFloatActiveSubpart = pNewFloatActiveSubPart;
  200.         if(pState->m_pFloatActiveSubpart)
  201.         {
  202.             if(pState->m_pFloatActiveSubpart->onMouseIn)
  203.                 pState->m_pFloatActiveSubpart->onMouseIn(pState->m_pFloatActiveSubpart);
  204.         }
  205.     }
  206. }
  207. //
  208. //
  209. //
  210. CPs_InterfacePart* IF_HitTestMouse(CPs_InterfaceWindowState* pState, const POINT* pptMouse)
  211. {
  212.     CPs_InterfacePart* pSubPart_Cursor;
  213.     // Walk through list drawing and adding to the valid rects list
  214.     for(pSubPart_Cursor = pState->m_pFirstSubPart; pSubPart_Cursor; pSubPart_Cursor = (CPs_InterfacePart*)pSubPart_Cursor->m_hNext)
  215.     {
  216.         if(PtInRect(&pSubPart_Cursor->m_rLocation, *pptMouse) == TRUE)
  217.         {
  218.             return pSubPart_Cursor;
  219.         }
  220.     }
  221.     return NULL;
  222. }
  223. //
  224. //
  225. //
  226. LRESULT CALLBACK exp_InterfaceWindowProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
  227. {
  228.     CPs_InterfaceWindowState* pState;
  229.     // Get the window's data object
  230.     if(uiMessage == WM_NCCREATE)
  231.     {
  232.         HMODULE hModApplication;
  233.         pState = (CPs_InterfaceWindowState*)((CREATESTRUCT*)lParam)->lpCreateParams;
  234.         pState->m_hWnd = hWnd;
  235.         SetWindowLong(hWnd, GWL_USERDATA, (LONG)pState);
  236.         // Setup icons
  237.         hModApplication = GetModuleHandle(NULL);
  238.         SendMessage(hWnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)LoadIcon(hModApplication, MAKEINTRESOURCE(APP_ICON)));
  239.         SendMessage(hWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)LoadIcon(hModApplication, MAKEINTRESOURCE(APP_ICON)));
  240.     }
  241.     else
  242.         pState = (CPs_InterfaceWindowState*)GetWindowLong(hWnd, GWL_USERDATA);
  243.     // We get some messages before the window gets it's WM_NCCREATE!!! (just how bad is Windows eh???)
  244.     if(!pState)
  245.         return DefWindowProc(hWnd, uiMessage, wParam, lParam);
  246.     CP_CHECKOBJECT(pState);
  247.     // Message handlers
  248.     switch(uiMessage)
  249.     {
  250.     case WM_MOUSEMOVE:
  251.         if(pState->m_bMouseCaptured)
  252.         {
  253.             if(pState->m_hndlr_onMouseMove)
  254.                 pState->m_hndlr_onMouseMove(pState, MAKEPOINTS(lParam), (SHORT)wParam);
  255.         }
  256.         else
  257.         {
  258.             CPs_InterfacePart* pHitSubPart;
  259.             POINT ptMouse;
  260.             ptMouse.x = (short)LOWORD(lParam);
  261.             ptMouse.y = (short)HIWORD(lParam);
  262.             pHitSubPart = IF_HitTestMouse(pState, &ptMouse);
  263.             IF_SetFloatActiveSubPart(pState, pHitSubPart);
  264.         }
  265.         return 0;
  266.     case WM_LBUTTONDOWN:
  267.         {
  268.             CPs_InterfacePart* pHitSubPart;
  269.             POINT ptMouse;
  270.             ptMouse.x = (short)LOWORD(lParam);
  271.             ptMouse.y = (short)HIWORD(lParam);
  272.             pHitSubPart = IF_HitTestMouse(pState, &ptMouse);
  273.             if(pHitSubPart && pHitSubPart->onMouseButton_LDown)
  274.             {
  275.                 SetCapture(pState->m_hWnd);
  276.                 pState->m_pActiveSubpart = pHitSubPart;
  277.                 pHitSubPart->onMouseButton_LDown(pHitSubPart, MAKEPOINTS(lParam));
  278.             }
  279.         }
  280.         return 0;
  281.     case WM_LBUTTONUP:
  282.         if(pState->m_bMouseCaptured)
  283.         {
  284.             if(pState->m_hndlr_onMouseButton_LUp)
  285.                 pState->m_hndlr_onMouseButton_LUp(pState, MAKEPOINTS(lParam), (SHORT)wParam);
  286.         }
  287.         else
  288.         {
  289.             if(pState->m_pActiveSubpart)
  290.             {
  291.                 ReleaseCapture();
  292.                 if(pState->m_pActiveSubpart->onMouseButton_LUp)
  293.                     pState->m_pActiveSubpart->onMouseButton_LUp(pState->m_pActiveSubpart, MAKEPOINTS(lParam));
  294.                 pState->m_pActiveSubpart = NULL;
  295.             }
  296.         }
  297.         return 0;
  298.     case WM_NCDESTROY:
  299.         IF_CleanupState(pState);
  300.         break;
  301.     case WM_CREATE:
  302.         {
  303.             const CREATESTRUCT* pCS = (const CREATESTRUCT*)lParam;
  304.             // Update size/pos cache
  305.             pState->m_ptWindowPos.x = pCS->x;
  306.             pState->m_ptWindowPos.y = pCS->y;
  307.             pState->m_szWindowSize.cx = pCS->cx;
  308.             pState->m_szWindowSize.cy = pCS->cy;
  309.             // Reposition any subitems
  310.             IF_UpdateSubPartLayout(pState);
  311.             // Callback
  312.             if(pState->m_hndlr_onCreate)
  313.             {
  314.                 RECT rInitialPos;
  315.                 rInitialPos.left = 0;
  316.                 rInitialPos.top = 0;
  317.                 rInitialPos.right = pCS->cx;
  318.                 rInitialPos.bottom = pCS->cy;
  319.                 pState->m_hndlr_onCreate(pState, &rInitialPos);
  320.             }
  321.             IF_RebuildRegion(pState);
  322.         }
  323.         return 0;
  324.     case WM_DESTROY:
  325.         if(pState->m_hndlr_onDestroy)
  326.             pState->m_hndlr_onDestroy(pState);
  327.         IF_RemoveAllSubparts(pState);
  328.         break;
  329.     case WM_NCHITTEST:
  330.         {
  331.             CPs_InterfacePart* pSubPart_Cursor;
  332.             POINT ptMouse;
  333.             ptMouse.x = (short)LOWORD(lParam) - pState->m_ptWindowPos.x;
  334.             ptMouse.y = (short)HIWORD(lParam) - pState->m_ptWindowPos.y;
  335.             // First perform hit testing on subparts
  336.             for(pSubPart_Cursor = pState->m_pFirstSubPart; pSubPart_Cursor; pSubPart_Cursor = (CPs_InterfacePart*)pSubPart_Cursor->m_hNext)
  337.             {
  338.                 if(PtInRect(&pSubPart_Cursor->m_rLocation, ptMouse) == TRUE)
  339.                     return HTCLIENT;
  340.             }
  341.             // If the window is sizable - perform hit testing on edges
  342.             if(pState->m_dwStyle & CPC_INTERFACE_STYLE_RESIZING)
  343.             {
  344.                 // Is the mouse inside the size bands
  345.                 // - top band
  346.                 if(ptMouse.y < CPC_SIZEBORDER)
  347.                 {
  348.                     // Are we in a corner
  349.                     // - left
  350.                     if(ptMouse.x < CPC_SIZEBORDER)
  351.                         return HTTOPLEFT;
  352.                     // - right
  353.                     else if(ptMouse.x > (pState->m_szWindowSize.cx - CPC_SIZEBORDER) )
  354.                         return HTTOPRIGHT;
  355.                     else
  356.                         return HTTOP;
  357.                 }
  358.                 // - bottom band
  359.                 else if(ptMouse.y > (pState->m_szWindowSize.cy - CPC_SIZEBORDER) )
  360.                 {
  361.                     // Are we in a corner
  362.                     // - left
  363.                     if(ptMouse.x < CPC_SIZEBORDER)
  364.                         return HTBOTTOMLEFT;
  365.                     // - right
  366.                     else if(ptMouse.x > (pState->m_szWindowSize.cx - CPC_SIZEBORDER) )
  367.                         return HTBOTTOMRIGHT;
  368.                     else
  369.                         return HTBOTTOM;
  370.                 }
  371.                 // - left band
  372.                 else if(ptMouse.x < CPC_SIZEBORDER)
  373.                     return HTLEFT;
  374.                 // - right band
  375.                 else if(ptMouse.x > (pState->m_szWindowSize.cx - CPC_SIZEBORDER) )
  376.                     return HTRIGHT;
  377.             }
  378.             // - return the caption so that the window is dragged
  379.             return HTCAPTION;
  380.         }
  381.     case WM_WINDOWPOSCHANGED:
  382.         {
  383.             const WINDOWPOS* pWP = (const WINDOWPOS*)lParam;
  384.             RECT rNewPos;
  385.             BOOL bSizeChanged;
  386.             rNewPos.left = pWP->x;
  387.             rNewPos.right = pWP->x + pWP->cx;
  388.             rNewPos.top = pWP->y;
  389.             rNewPos.bottom = pWP->y + pWP->cy;
  390.             bSizeChanged = (pWP->flags & SWP_NOSIZE) ? FALSE : TRUE;
  391.             pState->m_ptWindowPos.x = pWP->x;
  392.             pState->m_ptWindowPos.y = pWP->y;
  393.             pState->m_szWindowSize.cx = pWP->cx;
  394.             pState->m_szWindowSize.cy = pWP->cy;
  395.             if(bSizeChanged)
  396.             {
  397.                 IF_UpdateSubPartLayout(pState);
  398.                 IF_RebuildRegion(pState);
  399.             }
  400.             // Perform callback
  401.             if(pState->m_hndlr_onPosChange)
  402.                 pState->m_hndlr_onPosChange(pState, &rNewPos, bSizeChanged);
  403.         }
  404.         return 0;
  405.     case WM_NCCALCSIZE:
  406.         // We do not wish to have any window area lost to captions etc (also prevent the system
  407.         // from preserving our window contents during a resize
  408.         return WVR_REDRAW;
  409.     case WM_NCACTIVATE:
  410.         return TRUE;
  411.     case WM_NCPAINT:
  412.         return 0;
  413.     case WM_NCMOUSEMOVE:
  414.         IF_SetFloatActiveSubPart(pState, NULL);
  415.         return 0;
  416.     case WM_MOUSELEAVE:
  417.         IF_SetFloatActiveSubPart(pState, NULL);
  418.         pState->m_bMouseLeaveEventSet = FALSE;
  419.         return 0;
  420.     case WM_CLOSE:
  421.         if(pState->m_hndlr_onClose)
  422.         {
  423.             pState->m_hndlr_onClose(pState);
  424.             return 0;
  425.         }
  426.         break;
  427.     case WM_PAINT:
  428.         {
  429.             PAINTSTRUCT ps;
  430.             CPs_DrawContext drawcontext;
  431.             // Prepare for draw
  432.             drawcontext.m_dcDraw = BeginPaint(hWnd, &ps);
  433.             drawcontext.m_ptOffset.x = 0;
  434.             drawcontext.m_ptOffset.y = 0;
  435.             GetClipBox(drawcontext.m_dcDraw, &drawcontext.m_rClip);
  436.             IF_PaintWindow(pState, &drawcontext);
  437.             // Cleanup
  438.             EndPaint(hWnd, &ps);
  439.         }
  440.         return 0;
  441.     case WM_ACTIVATE:
  442.         if(LOWORD(wParam) == WA_ACTIVE)
  443.             SetFocus(hWnd);
  444.         return 0;
  445.     case WM_SYSKEYDOWN:
  446.     case WM_KEYDOWN:
  447.         if(pState->m_hndlr_onKeyDown)
  448.         {
  449.             const BOOL bAltIsDown = (GetAsyncKeyState(VK_MENU)  & 0x8000) ? TRUE : FALSE;
  450.             const BOOL bCtrlIsDown = (GetAsyncKeyState(VK_CONTROL)  & 0x8000) ? TRUE : FALSE;
  451.             const BOOL bShiftIsDown = (GetAsyncKeyState(VK_SHIFT)  & 0x8000) ? TRUE : FALSE;
  452.             pState->m_hndlr_onKeyDown(pState, (unsigned int)wParam, bAltIsDown, bCtrlIsDown, bShiftIsDown);
  453.         }
  454.         return 0;
  455.     case WM_DROPFILES:
  456.         if(pState->m_hndlr_onDropFiles)
  457.             pState->m_hndlr_onDropFiles(pState, (HDROP)wParam);
  458.         return 0;
  459.     case WM_GETMINMAXINFO:
  460.         {
  461.             MINMAXINFO* pMinMaxInfo = (MINMAXINFO*)lParam;
  462.             RECT rWorkArea;
  463.             if(pfnGetMonitorInfo)
  464.             {
  465.                 // Multimonitors are supported by this OS
  466.                 MONITORINFO mi;
  467.                 HMONITOR hmon = pfnMonitorFromWindow(pState->m_hWnd, MONITOR_DEFAULTTOPRIMARY);
  468.                 mi.cbSize = sizeof(mi);
  469.                 pfnGetMonitorInfo(hmon, &mi);
  470.                 // Get the work area of this monitor - as an offset from this monitors virtual space
  471.                 rWorkArea.left = mi.rcWork.left - mi.rcMonitor.left;
  472.                 rWorkArea.right = mi.rcWork.right - mi.rcMonitor.left;
  473.                 rWorkArea.top = mi.rcWork.top - mi.rcMonitor.top;
  474.                 rWorkArea.bottom = mi.rcWork.bottom - mi.rcMonitor.top;
  475.             }
  476.             else
  477.             {
  478.                 // Single monitor only OS
  479.                 SystemParametersInfo(SPI_GETWORKAREA, 0, &rWorkArea, 0);
  480.             }
  481.             pMinMaxInfo->ptMinTrackSize.x = pState->m_szMinSize.cx;
  482.             pMinMaxInfo->ptMinTrackSize.y = pState->m_szMinSize.cy;
  483.             pMinMaxInfo->ptMaxPosition.x = rWorkArea.left;
  484.             pMinMaxInfo->ptMaxPosition.y = rWorkArea.top;
  485.             pMinMaxInfo->ptMaxSize.x = rWorkArea.right-rWorkArea.left;
  486.             pMinMaxInfo->ptMaxSize.y = rWorkArea.bottom-rWorkArea.top;
  487.             pMinMaxInfo->ptMaxTrackSize.x = pMinMaxInfo->ptMaxSize.x;
  488.             pMinMaxInfo->ptMaxTrackSize.y = pMinMaxInfo->ptMaxSize.y;
  489.         }
  490.         return 0;
  491.     case WM_SETFOCUS:
  492.         if(pState->m_hndlr_onFocus)
  493.             pState->m_hndlr_onFocus(pState, TRUE);
  494.         return 0;
  495.     case WM_KILLFOCUS:
  496.         if(pState->m_hndlr_onFocus)
  497.             pState->m_hndlr_onFocus(pState, FALSE);
  498.         return 0;
  499.     case WM_COMMAND:
  500.         if(pState->m_hndlr_onCommandMessage)
  501.             pState->m_hndlr_onCommandMessage(pState, wParam, lParam);
  502.         return 0;
  503.     }
  504.     // Route message (to windows if it isn't handled)
  505.     if(uiMessage >= WM_APP && pState->m_hndlr_onAppMessage)
  506.         return pState->m_hndlr_onAppMessage(pState, uiMessage, wParam, lParam);
  507.     return DefWindowProc(hWnd, uiMessage, wParam, lParam);
  508. }
  509. //
  510. //
  511. //
  512. void IF_RebuildRegion(CP_HINTERFACE hInterface)
  513. {
  514.     CPs_InterfaceWindowState* pState;
  515.     HBITMAP bmOld;
  516.     HBITMAP bmSurface;
  517.     HDC dcDraw;
  518.     RECT rClient;
  519.     HDC dcScreen;
  520.     HRGN rgnWindow;
  521.     // Init
  522.     pState = (CPs_InterfaceWindowState*)hInterface;
  523.     CP_CHECKOBJECT(pState);
  524.     // There was no region last time - don't bother looking for one now
  525.     if(pState->m_bSkipRegion)
  526.         return;
  527.     // Create an offscreen
  528.     GetClientRect(pState->m_hWnd, &rClient);
  529.     bmSurface = CreateBitmap(rClient.right, rClient.bottom, 1, 1, NULL);
  530.     dcScreen = GetDC(pState->m_hWnd);
  531.     dcDraw = CreateCompatibleDC(dcScreen);
  532.     bmOld = (HBITMAP)SelectObject(dcDraw, bmSurface);
  533.     ReleaseDC(pState->m_hWnd, dcScreen);
  534.     // Draw the window
  535.     {
  536.         CPs_DrawContext drawcontext;
  537.         drawcontext.m_dcDraw = dcDraw;
  538.         drawcontext.m_ptOffset.x = 0;
  539.         drawcontext.m_ptOffset.y = 0;
  540.         drawcontext.m_rClip = rClient;
  541.         IF_PaintWindow(pState, &drawcontext);
  542.     }
  543.     // Cleanup
  544.     SelectObject(dcDraw, bmOld);
  545.     DeleteDC(dcDraw);
  546.     // Setup region
  547.     rgnWindow = main_bitmap_to_region_1bit(bmSurface, glb_pSkin->m_clrTransparent);
  548.     DeleteObject(bmSurface);
  549.     SetWindowRgn( pState->m_hWnd,
  550.                   rgnWindow,
  551.                   TRUE);
  552.     if(!rgnWindow)
  553.         pState->m_bSkipRegion = TRUE;
  554. }
  555. //
  556. //
  557. //
  558. void IF_PaintWindow(CPs_InterfaceWindowState* pState, CPs_DrawContext* pContext)
  559. {
  560.     // Walk through list drawing and adding to the valid rects list
  561.     CPs_InterfacePart* pSubPart_Cursor;
  562.     for(pSubPart_Cursor = pState->m_pFirstSubPart; pSubPart_Cursor; pSubPart_Cursor = (CPs_InterfacePart*)pSubPart_Cursor->m_hNext)
  563.     {
  564.         if(pSubPart_Cursor->Draw)
  565.         {
  566.             pSubPart_Cursor->Draw(pSubPart_Cursor, pContext);
  567.             ExcludeClipRect(pContext->m_dcDraw,
  568.                             pSubPart_Cursor->m_rLocation.left, pSubPart_Cursor->m_rLocation.top,
  569.                             pSubPart_Cursor->m_rLocation.right, pSubPart_Cursor->m_rLocation.bottom);
  570.         }
  571.     }
  572.     // Perform callback
  573.     if(pState->m_hndlr_onDraw)
  574.         pState->m_hndlr_onDraw(pState, pContext);
  575. }
  576. //
  577. //
  578. //
  579. void IF_SetMinSize(CP_HINTERFACE hInterface, const SIZE* pMinSize)
  580. {
  581.     CPs_InterfaceWindowState* pState;
  582.     // Init
  583.     pState = (CPs_InterfaceWindowState*)hInterface;
  584.     CP_CHECKOBJECT(pState);
  585.     pState->m_szMinSize = *pMinSize;
  586. }
  587. //
  588. //
  589. //
  590. void IF_PostAppMessage(CP_HINTERFACE hInterface, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
  591. {
  592.     CPs_InterfaceWindowState* pState;
  593.     // Init
  594.     pState = (CPs_InterfaceWindowState*)hInterface;
  595.     CP_CHECKOBJECT(pState);
  596.     CP_ASSERT(uiMessage >= WM_APP);
  597.     PostMessage(pState->m_hWnd, uiMessage, wParam, lParam);
  598. }
  599. //
  600. //
  601. //
  602. void IF_SetMouseCapture(CP_HINTERFACE hInterface, wp_IF_onMouseMessage pfn_onMouseMove, wp_IF_onMouseMessage pfn_onMouseButton_LUp)
  603. {
  604.     CPs_InterfaceWindowState* pState;
  605.     // Init
  606.     pState = (CPs_InterfaceWindowState*)hInterface;
  607.     CP_CHECKOBJECT(pState);
  608.     pState->m_bMouseCaptured = TRUE;
  609.     pState->m_hndlr_onMouseMove = pfn_onMouseMove;
  610.     pState->m_hndlr_onMouseButton_LUp = pfn_onMouseButton_LUp;
  611.     SetCapture(pState->m_hWnd);
  612. }
  613. //
  614. //
  615. //
  616. void IF_ReleaseMouseCapture(CP_HINTERFACE hInterface)
  617. {
  618.     CPs_InterfaceWindowState* pState;
  619.     // Init
  620.     pState = (CPs_InterfaceWindowState*)hInterface;
  621.     CP_CHECKOBJECT(pState);
  622.     pState->m_bMouseCaptured = FALSE;
  623.     ReleaseCapture();
  624. }
  625. //
  626. //
  627. //
  628. void IF_RemoveAllSubparts(CP_HINTERFACE hInterface)
  629. {
  630.     CPs_InterfaceWindowState* pState;
  631.     CPs_InterfacePart* pSubPart_Cursor;
  632.     CPs_InterfacePart* pSubPart_Next;
  633.     // Init
  634.     pState = (CPs_InterfaceWindowState*)hInterface;
  635.     CP_CHECKOBJECT(pState);
  636.     // Walk through list destroying subparts
  637.     for(pSubPart_Cursor = pState->m_pFirstSubPart; pSubPart_Cursor; pSubPart_Cursor = pSubPart_Next)
  638.     {
  639.         pSubPart_Next = (CPs_InterfacePart*)pSubPart_Cursor->m_hNext;
  640.         IP_Destroy(pSubPart_Cursor);
  641.     }
  642.     pState->m_pFirstSubPart = NULL;
  643. }
  644. //
  645. //
  646. //
  647. void IF_AddSubPart_CommandButton( CP_HINTERFACE hInterface,
  648.                                   const DWORD dwAlign,
  649.                                   const POINT* pptOffset,
  650.                                   CPs_Image_WithState* pStateImage,
  651.                                   wp_Verb pfnVerb)
  652. {
  653.     CPs_InterfaceWindowState* pState;
  654.     CPs_InterfacePart* pSubPart_Next;
  655.     // Init
  656.     pState = (CPs_InterfaceWindowState*)hInterface;
  657.     CP_CHECKOBJECT(pState);
  658.     // Add new head to list
  659.     pSubPart_Next = pState->m_pFirstSubPart;
  660.     // Setup new part
  661.     pState->m_pFirstSubPart = IP_Create_CommandButton(pfnVerb, pStateImage);
  662.     pState->m_pFirstSubPart->m_hNext = pSubPart_Next;
  663.     pState->m_pFirstSubPart->m_hOwner = hInterface;
  664.     pState->m_pFirstSubPart->m_dwAlign = dwAlign;
  665.     pState->m_pFirstSubPart->m_bRectAlignMode = FALSE;
  666.     pState->m_pFirstSubPart->m_ptOffset = *pptOffset;
  667.     pState->m_pFirstSubPart->m_szSize.cx = pStateImage->m_pImage->m_szSize.cx;
  668.     pState->m_pFirstSubPart->m_szSize.cy = pStateImage->m_iStateHeight;
  669. }
  670. //
  671. //
  672. //
  673. void IF_AddSubPart_Indicator( CP_HINTERFACE hInterface,
  674.                               const char* pcName,
  675.                               const DWORD dwAlign,
  676.                               const RECT* prPosition)
  677. {
  678.     CPs_InterfaceWindowState* pState;
  679.     CPs_InterfacePart* pSubPart_Next;
  680.     // Init
  681.     pState = (CPs_InterfaceWindowState*)hInterface;
  682.     CP_CHECKOBJECT(pState);
  683.     // Add new head to list
  684.     pSubPart_Next = pState->m_pFirstSubPart;
  685.     // Setup new part
  686.     pState->m_pFirstSubPart = IP_Create_Indicator(pcName);
  687.     pState->m_pFirstSubPart->m_hNext = pSubPart_Next;
  688.     pState->m_pFirstSubPart->m_hOwner = hInterface;
  689.     pState->m_pFirstSubPart->m_dwAlign = dwAlign;
  690.     pState->m_pFirstSubPart->m_bRectAlignMode = TRUE;
  691.     pState->m_pFirstSubPart->m_rPosition = *prPosition;
  692. }
  693. //
  694. //
  695. //
  696. void IF_UpdateSubPartLayout(CP_HINTERFACE hInterface)
  697. {
  698.     CPs_InterfaceWindowState* pState;
  699.     CPs_InterfacePart* pSubPart_Cursor;
  700.     // Init
  701.     pState = (CPs_InterfaceWindowState*)hInterface;
  702.     CP_CHECKOBJECT(pState);
  703.     // Walk through list setting position
  704.     for(pSubPart_Cursor = pState->m_pFirstSubPart; pSubPart_Cursor; pSubPart_Cursor = (CPs_InterfacePart*)pSubPart_Cursor->m_hNext)
  705.     {
  706.         if(pSubPart_Cursor->m_bRectAlignMode == TRUE)
  707.         {
  708.             // Set position
  709.             // - left
  710.             if(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_LEFT)
  711.                 pSubPart_Cursor->m_rLocation.left = pSubPart_Cursor->m_rPosition.left;
  712.             else
  713.             {
  714.                 CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_RIGHT);
  715.                 pSubPart_Cursor->m_rLocation.left = pState->m_szWindowSize.cx - pSubPart_Cursor->m_rPosition.right - pSubPart_Cursor->m_rPosition.left;
  716.             }
  717.             // - right
  718.             if(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_RIGHT)
  719.                 pSubPart_Cursor->m_rLocation.right = pState->m_szWindowSize.cx - pSubPart_Cursor->m_rPosition.right;
  720.             else
  721.             {
  722.                 CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_LEFT);
  723.                 pSubPart_Cursor->m_rLocation.right = pSubPart_Cursor->m_rLocation.left + pSubPart_Cursor->m_rPosition.right;
  724.             }
  725.             // - top
  726.             if(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_TOP)
  727.                 pSubPart_Cursor->m_rLocation.top = pSubPart_Cursor->m_rPosition.top;
  728.             else
  729.             {
  730.                 CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_BOTTOM);
  731.                 pSubPart_Cursor->m_rLocation.top = pState->m_szWindowSize.cy - pSubPart_Cursor->m_rPosition.bottom - pSubPart_Cursor->m_rPosition.top;
  732.             }
  733.             // - bottom
  734.             if(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_BOTTOM)
  735.                 pSubPart_Cursor->m_rLocation.bottom = pState->m_szWindowSize.cy - pSubPart_Cursor->m_rPosition.bottom;
  736.             else
  737.             {
  738.                 CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_TOP);
  739.                 pSubPart_Cursor->m_rLocation.bottom = pSubPart_Cursor->m_rLocation.top + pSubPart_Cursor->m_rPosition.bottom;
  740.             }
  741.         }
  742.         else
  743.         {
  744.             // Set position
  745.             if(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_LEFT)
  746.                 pSubPart_Cursor->m_rLocation.left = pSubPart_Cursor->m_ptOffset.x;
  747.             else
  748.             {
  749.                 CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_RIGHT);
  750.                 pSubPart_Cursor->m_rLocation.left = pState->m_szWindowSize.cx - pSubPart_Cursor->m_szSize.cx - pSubPart_Cursor->m_ptOffset.x;
  751.             }
  752.             pSubPart_Cursor->m_rLocation.right = pSubPart_Cursor->m_rLocation.left + pSubPart_Cursor->m_szSize.cx;
  753.             if(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_TOP)
  754.                 pSubPart_Cursor->m_rLocation.top = pSubPart_Cursor->m_ptOffset.y;
  755.             else
  756.             {
  757.                 CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_BOTTOM);
  758.                 pSubPart_Cursor->m_rLocation.top = pState->m_szWindowSize.cy - pSubPart_Cursor->m_szSize.cy - pSubPart_Cursor->m_ptOffset.y;
  759.             }
  760.             pSubPart_Cursor->m_rLocation.bottom = pSubPart_Cursor->m_rLocation.top + pSubPart_Cursor->m_szSize.cy;
  761.         }
  762.     }
  763. }
  764. //
  765. //
  766. //