Game Accessibility Library logo SourceForge.net Logo
Game Accessibility Suite: CATGUI/CATWindow_Win32.cpp Source File

CATWindow_Win32.cpp

Go to the documentation of this file.
00001 //---------------------------------------------------------------------------
00002 /// \file GGWindow_Win32.cpp
00003 /// \brief Win32 CATWindow implementation
00004 /// \ingroup CATGUI
00005 ///
00006 /// Copyright (c) 2003-2008 by Michael Ellison.
00007 /// See COPYING.txt for the \ref gaslicense License (MIT License).
00008 ///
00009 // $Author: mikeellison $
00010 // $Date: 2008-01-31 20:30:30 -0600 (Thu, 31 Jan 2008) $
00011 // $Revision:   $
00012 // $NoKeywords: $
00013 //
00014 //---------------------------------------------------------------------------
00015 
00016 // Using new win32 features (post 95)
00017 #include "CATWindow.h"
00018 
00019 #include "CATApp.h"
00020 #include "CATEventDefs.h"
00021 #include "CATCursor.h"
00022 #include "CATKeystroke.h"
00023 #include "CATColor.h"
00024 #include "CATControlWnd.h"
00025 #include "CATMenu.h"
00026 #include "CATListBox.h"
00027 #include "CATGuiResDefs.h"
00028 #include "CATOSFuncs.h"
00029 #include "CATAccessible.h"
00030 
00031 __inline CATPOINT CATLParamToPoint(LPARAM lParam)
00032 {
00033     CATPOINT pt;
00034     pt.x = (CATInt32)(CATUInt16)(LOWORD(lParam));
00035     pt.y = (CATInt32)(CATUInt16)(HIWORD(lParam));
00036     return pt;
00037 }
00038 
00039 
00040 
00041 LRESULT CALLBACK CATWindow::WindowProc( HWND hwnd,      // handle to window
00042                                         UINT uMsg,      // message identifier
00043                                         WPARAM wParam,  // first message parameter
00044                                         LPARAM lParam )  // second message parameter
00045 {
00046     // Add our information into window on create 
00047     // (don't return yet, we handle the WM_CREATE the normal way too later)
00048     if (uMsg == WM_CREATE)
00049     {
00050         // Store this* for our object in the window
00051         LPCREATESTRUCT lpc = (LPCREATESTRUCT)lParam;
00052         SetWindowLong(hwnd,GWL_USERDATA,(LONG)(UINT_PTR)lpc->lpCreateParams);      
00053 
00054         // Store halftone palette in the window as well.
00055         HDC hdc = GetDC(hwnd);
00056         HPALETTE palette = CreateHalftonePalette(hdc);
00057         ReleaseDC(hwnd,hdc);      
00058         SetWindowLong( hwnd,0, (CATInt32)(UINT_PTR)palette);
00059 
00060         // Flush changes to window data
00061         SetWindowPos(hwnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOZORDER|SWP_NOSIZE);      
00062     }
00063 
00064     // Retrieve information stored in the window
00065     CATWindow* theWnd     = (CATWindow*)(UINT_PTR)GetWindowLong(hwnd,GWL_USERDATA);
00066     HPALETTE  appPalette = (HPALETTE)(UINT_PTR)GetWindowLong(hwnd,0);
00067 
00068     if (theWnd == 0)
00069     {
00070         return DefWindowProc(hwnd,uMsg,wParam,lParam);
00071     }
00072 
00073 
00074     // Handle WM's that we wont need to override, convert
00075     // any we might be interest in into CATEvent's and pass
00076     // to our OnEvent() handler.   
00077     bool handled = false;
00078     LRESULT lRes = 0;
00079 
00080     if (theWnd->fWindow == hwnd)
00081     {
00082         switch (uMsg)
00083         {
00084             case CATWM_EVENTPOSTED:    theWnd->ProcessPostedEvent(); break;
00085             case WM_GETOBJECT:     lRes = theWnd->OSGetObject    (hwnd, uMsg, wParam, lParam, handled); break;
00086             case WM_DROPFILES:     lRes = theWnd->OSDropFiles    (hwnd, uMsg, wParam, lParam, handled); break;
00087             case WM_SIZE:          lRes = theWnd->OSOnSize       (hwnd, uMsg, wParam, lParam, handled); break;                
00088             case WM_GETMINMAXINFO: lRes = theWnd->OSOnMinMax     (hwnd, uMsg, wParam, lParam, handled); break;
00089             case WM_KEYDOWN:       lRes = theWnd->OSOnKeyDown    (hwnd, uMsg, wParam, lParam, handled); break;
00090             case WM_KEYUP:         lRes = theWnd->OSOnKeyUp      (hwnd, uMsg, wParam, lParam, handled); break;
00091             case WM_APPCOMMAND:    lRes = theWnd->OSOnAppCmd     (hwnd, uMsg, wParam, lParam, handled); break;
00092             case WM_PAINT:         lRes = theWnd->OSOnPaint      (hwnd, uMsg, wParam, lParam, handled); break;
00093             case WM_MEASUREITEM:   lRes = theWnd->OSOnMeasureItem(hwnd, uMsg, wParam, lParam, handled); break;
00094             case WM_DRAWITEM:      lRes = theWnd->OSOnDrawItem   (hwnd, uMsg, wParam, lParam, handled); break;
00095             case WM_CTLCOLOREDIT:
00096             case WM_CTLCOLORSTATIC:
00097             case WM_CTLCOLORLISTBOX:
00098             case WM_CTLCOLORSCROLLBAR: 
00099                                 lRes = theWnd->OSGetControlColors(hwnd, uMsg, wParam, lParam, handled); break;                                
00100 
00101             case WM_MOUSEWHEEL:
00102                 {
00103                     CATPOINT    pt       = CATLParamToPoint(lParam);
00104                     CATMODKEY   modKey   = GetModifierKeys();
00105                     CATFloat32  rotation = ((CATFloat32)(CATInt16)HIWORD(wParam)) / (CATFloat32)WHEEL_DELTA;
00106 
00107                     ::ScreenToClient(hwnd,(LPPOINT)&pt);
00108 
00109                     theWnd->OnMouseWheel(pt,rotation,modKey);
00110                 }
00111                 break;
00112 
00113             case WM_MOUSEHOVER:
00114                 {
00115                     CATPOINT pt = CATLParamToPoint(lParam);
00116                     CATMODKEY modKey = GetModifierKeys();  
00117 
00118                     bool leftBtn = (wParam & MK_LBUTTON)?true:false;
00119 
00120                     theWnd->OnMouseHover(pt,leftBtn,modKey);
00121                     
00122                     SetTrackMouse(hwnd);
00123                 }
00124                 break;
00125             case WM_MOUSEMOVE:
00126                 {
00127                     if (theWnd->fMouseInWindow == false)
00128                     {
00129                         // Setup window to track mouse events      
00130                         SetTrackMouse(hwnd);
00131                     }
00132 
00133                     CATMODKEY modKey = GetModifierKeys();               
00134                     CATPOINT pt = CATLParamToPoint(lParam);
00135 
00136                     if ((pt.x != theWnd->fLastPoint.x) ||
00137                         (pt.y != theWnd->fLastPoint.y))
00138                     {
00139                         theWnd->fLastPoint = pt;
00140                         theWnd->OnMouseMove( pt, 
00141                                              (wParam & MK_LBUTTON)?true:false,
00142                                              modKey);
00143                         handled = true;
00144                     }
00145                 }
00146                 break;
00147 
00148             case WM_MOUSELEAVE:
00149                 {
00150                     POINT pt;
00151                     GetCursorPos(&pt);
00152                     CATRect absRect = theWnd->GetRectAbs(true);
00153                     if (!PtInRect((RECT*)&(CATRECT)absRect,pt))
00154                     {
00155                         theWnd->OnMouseLeave();
00156                     }
00157                     else
00158                     {
00159                         theWnd->fMouseInWindow = false;
00160                     }
00161                 }
00162                 break;
00163             case WM_LBUTTONDBLCLK:
00164                 {                    
00165                     CATPOINT  pt     = CATLParamToPoint(lParam);
00166                     CATMODKEY modKey = GetModifierKeys();
00167                     theWnd->OnMouseDoubleClick(pt,modKey);
00168                     handled = true;
00169                 }
00170                 break;
00171             case WM_LBUTTONDOWN: 
00172                 {
00173                     ::SetFocus(theWnd->fWindow);
00174                     ::SetTimer(hwnd, CATWM_MOUSETIMER, kMOUSEFILTERFREQ, 0);
00175                     CATPOINT  pt     = CATLParamToPoint(lParam);
00176                     CATMODKEY modKey = GetModifierKeys();
00177                     theWnd->OnMouseDown(pt, modKey);
00178                     handled = true;
00179                 }
00180                 break;
00181             case WM_RBUTTONDOWN:
00182                 {
00183                     CATPOINT  pt     = CATLParamToPoint(lParam);
00184                     CATMODKEY modKey = GetModifierKeys();
00185                     theWnd->OnRightMouseDown(pt, modKey);
00186                     handled = true;
00187                 }
00188                 break;
00189             case WM_RBUTTONUP:
00190                 {
00191                     CATPOINT  pt     = CATLParamToPoint(lParam);
00192                     CATMODKEY modKey = GetModifierKeys();
00193                     theWnd->OnRightMouseUp(pt, modKey);
00194                     handled = true;
00195                 }
00196                 break;
00197             case WM_LBUTTONUP:
00198                 {
00199                     ::KillTimer(hwnd, CATWM_MOUSETIMER);            
00200                     CATPOINT  pt     = CATLParamToPoint(lParam);
00201                     CATMODKEY modKey = GetModifierKeys();
00202                     theWnd->OnMouseUp(pt,modKey);
00203                     handled = true;
00204                 }
00205                 break;      
00206             case WM_MOVE:
00207                 {
00208                     CATPOINT pt = CATLParamToPoint(lParam);
00209                     // WM_MOVE is client position, so we're good to go.
00210                     theWnd->OnMove(pt);
00211                     handled = true;
00212                 }
00213                 break;
00214                 //-------------------------------------------------------
00215                 //-------------------------------------------------------
00216             case WM_SETCURSOR:
00217                 {
00218                     if (LOWORD(lParam) == HTCLIENT)
00219                     {
00220 
00221                         SetCursor(theWnd->fCursor.GetOSCursor());
00222                         handled = true;
00223                         lRes    = 1;
00224                     }
00225                 }
00226                 break;
00227                 //-------------------------------------------------------
00228             case WM_SYSCHAR:
00229             case WM_SYSCOMMAND:
00230                 break;
00231             case WM_CHAR:
00232                 {
00233                     CATMODKEY modKey = GetModifierKeys();               
00234                     theWnd->OnKeyPress(CATKeystroke(wParam,CATKEY_NONE,modKey));
00235                     handled = true;
00236                 }
00237                 break;
00238 
00239             case WM_TIMER:
00240                 {
00241                     if (wParam == CATWM_MOUSETIMER)
00242                     {
00243                         CATMODKEY modKey = GetModifierKeys();
00244 
00245                         theWnd->OnMouseTimer(modKey);
00246 
00247                         lRes = 0;
00248                         handled = true;
00249                     }  
00250                     else if (wParam == CATWM_UPDATETIMER)
00251                     {
00252                         theWnd->OnWindowTimer();
00253                     }
00254                 }
00255                 break;
00256 
00257             case WM_SETFOCUS:                
00258                 break;
00259 
00260             case WM_GETDLGCODE :
00261                 lRes = DLGC_WANTALLKEYS;
00262                 handled = true;
00263                 break;   
00264 
00265             case WM_MOVING:
00266                 {
00267                     RECT* moveRect = (RECT*)lParam;
00268                     CATRect checkRect( moveRect->left,
00269                         moveRect->top, 
00270                         moveRect->right, 
00271                         moveRect->bottom);
00272 
00273                     // Framework really only knows about client area, and WM_MOVING is in
00274                     // non-client coords, so we need to give it the actual window rect for 
00275                     // comparisons.
00276 
00277                     CATRect wndRect = theWnd->OSGetWndRect();
00278 
00279                     // If the window changes the move rect and returns true, set
00280                     // the move rect to the changes.
00281                     if (theWnd->OnMoving(checkRect,wndRect))
00282                     {
00283                         moveRect->left = checkRect.left;
00284                         moveRect->top = checkRect.top;
00285                         moveRect->right = checkRect.right;
00286                         moveRect->bottom = checkRect.bottom;
00287                         lRes = 1;
00288                         handled = true;
00289                     }
00290                 }
00291                 break;
00292                 //-------------------------------------------------------
00293                 // When focus is killed, it may be to a child control.
00294                 // We should set that control as focused if it isn't.
00295             case WM_KILLFOCUS:
00296                 {               
00297                     std::map<CATWND,CATControlWnd*>::iterator iter = theWnd->fCWT.find((CATWND)wParam);
00298                     if (iter != theWnd->fCWT.end())
00299                     {
00300                         CATControlWnd* curControl = iter->second;
00301                         theWnd->SetFocus(curControl);
00302                     }
00303                 }  
00304                 break;
00305                 //-------------------------------------------------------
00306             case WM_CREATE:
00307                 {
00308                     handled = true;
00309                     lRes    = 0;
00310                 }
00311                 break;
00312                 //-------------------------------------------------------
00313             case WM_QUERYNEWPALETTE:
00314                 if ((HWND)wParam == theWnd->fWindow)
00315                 {           
00316                     HDC hDC = ::GetDC(theWnd->fWindow);
00317                     ::SelectPalette(hDC,appPalette,FALSE);
00318                     ::RealizePalette(hDC);
00319                     ::InvalidateRect(theWnd->fWindow,0,FALSE);
00320                     ::ReleaseDC(theWnd->fWindow,hDC);
00321                     handled  = true;
00322                     lRes     = 1;
00323                 }
00324                 break;
00325                 //-------------------------------------------------------
00326             case WM_PALETTECHANGED:
00327                 {
00328                     HDC hDC = ::GetDC(theWnd->fWindow);
00329                     ::SelectPalette(hDC,appPalette,FALSE);            
00330 
00331                     if (wParam != (DWORD)theWnd->fWindow)
00332                     {
00333                         ::RealizePalette(hDC);
00334                     }
00335 
00336                     ::UpdateColors(hDC);
00337                     ::ReleaseDC(theWnd->fWindow,hDC);               
00338                     handled  = true;
00339                     lRes     = 0;
00340                 }
00341                 break;
00342 
00343             case WM_DESTROY:
00344                 theWnd->OnDestroy();                  
00345                 DeleteObject(appPalette);
00346                 handled  = true;
00347                 lRes     = 0;
00348                 break;
00349 
00350                 //-------------------------------------------------------
00351             case WM_ERASEBKGND:
00352                 handled  = true;
00353                 lRes     = TRUE;
00354                 break;            
00355             //-------------------------------------------------------
00356 
00357         }   
00358     }
00359 
00360     if (!handled)
00361     {
00362         CATInt32 eventResult = (CATInt32)lRes;
00363         CATResult result = theWnd->OnEvent(CATEvent(CATEVENT_WINDOWS_EVENT,(CATInt32)hwnd,uMsg,wParam,lParam), eventResult);
00364         if (CATFAILED(result))
00365         {
00366             theWnd->DisplayError(result);
00367         }
00368         if (eventResult == 0)
00369         {
00370             lRes = ::DefWindowProc(hwnd,uMsg,wParam,lParam);
00371         }
00372         else
00373         {
00374             lRes = (LRESULT)eventResult;
00375         }
00376     }
00377 
00378     return lRes;
00379 }
00380 
00381 // RegWindow registers a window class if needed,
00382 // providing a string to reference it in the future.
00383 // \return CATResult - CAT_SUCCESS on success.
00384 CATResult CATWindow::RegWindow()
00385 {
00386     // Setup struct for registering class
00387     WNDCLASS wc;
00388     memset(&wc, 0, sizeof(wc));
00389 
00390 
00391     wc.cbClsExtra     = 0;                 // No class data right now..
00392     wc.cbWndExtra     = 4;  // Reserve space to store HPALETTE in the window
00393     wc.style          = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
00394     wc.lpfnWndProc    = WindowProc;
00395     wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
00396     wc.hInstance      = gApp->GetInstance();
00397 
00398     // Convert fIcon into an HICON rather than a raw image...
00399 
00400     HICON curIcon = 0;
00401 
00402     if (fIconPath.IsEmpty() == false)
00403     {
00404         CATString fullPath = gApp->GetSkin()->GetRootDir() + fIconPath;
00405         fUserIcon = curIcon = (HICON)::LoadImage(0,fullPath,IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_LOADFROMFILE);
00406     }
00407 
00408     if (curIcon == 0)
00409     {
00410         curIcon = LoadIcon(gApp->GetInstance(),MAKEINTRESOURCE(IDI_CATAPPICON));
00411     }
00412 
00413     wc.hIcon            = curIcon;
00414     wc.hCursor          = fCursor.GetOSCursor();       
00415     wc.lpszClassName    = fClassName.GetUnicodeBuffer();   
00416 
00417     // Purposefully leaving fClassName locked....
00418     ATOM resultClass = RegisterClass(&wc);
00419     fClassName.ReleaseBuffer();
00420 
00421     if (resultClass != 0)
00422     {
00423         return CAT_SUCCESS;
00424     }
00425 
00426     return CAT_ERR_WINDOW_CLASSREG_FAILED;
00427 }
00428 
00429 void CATWindow::GGUnregWindow()
00430 {
00431     CATASSERT(fRegistered == true, "Only unreg if already registered.");
00432     ::UnregisterClass(fClassName,gApp->GetInstance());
00433 
00434     if (fUserIcon)
00435     {
00436 #ifdef _WIN32
00437         ::DestroyIcon(fUserIcon);
00438         fUserIcon = 0;
00439 #endif
00440     }
00441 
00442 }
00443 
00444 CATResult CATWindow::OSCreateWnd( CATWND parentWnd)
00445 {
00446     CATASSERT(fWindow == 0, "Window already created... call ShowWnd() instead.");
00447 
00448     CATUInt32 style = OSGetWindowStyle();
00449 
00450     CATRect screenRect = fRect;
00451     screenRect.SetOrigin(this->fScreenPos);
00452     RECT realRect = *(RECT*)(CATRECT*)&screenRect;
00453     
00454     // Add in border size so client is at the desired size...
00455     AdjustWindowRect(&realRect,style,FALSE);
00456 
00457     // prevent under-shooting.... over shooting shouldn't really be possible yet
00458     if (realRect.left < 0)
00459     {
00460         CATInt32 xOff = -realRect.left;
00461         realRect.left += xOff;
00462         realRect.right += xOff;
00463     }
00464 
00465     if (realRect.top < 0)
00466     {
00467         CATInt32 yOff = -realRect.top;
00468         realRect.top += yOff;
00469         realRect.bottom += yOff;
00470     }
00471 
00472     fWindow = ::CreateWindowEx( WS_EX_ACCEPTFILES,
00473                                 fClassName,
00474                                 fName,
00475                                 style,
00476                                 realRect.left,
00477                                 realRect.top,
00478                                 realRect.right - realRect.left,
00479                                 realRect.bottom - realRect.top,
00480                                 parentWnd, 
00481                                 0, 
00482                                 gApp->GetInstance(),
00483                                 this);
00484 
00485     ::SetFocus(fWindow);
00486     this->SetTrackMouse(fWindow);
00487 
00488     fVisible = true;
00489 
00490     if (this->IsOverlapped() == false)
00491     {    
00492         if (fTitle.IsEmpty() == false)
00493         {
00494             ::SetWindowText(fWindow,fTitle);
00495         }
00496         else
00497         {
00498             ::SetWindowText(fWindow,fName);
00499         }
00500     }
00501 
00502     if (fWindow)
00503     {
00504         this->OnCreate();
00505         // Show and update the window      
00506         return CAT_SUCCESS;
00507     }
00508     else
00509     {
00510         CATASSERT(false,"Error creating window!");
00511     }
00512 
00513     return CATRESULT(CAT_ERR_WINDOW_CREATE_FAILED);
00514 
00515 }
00516 
00517 void CATWindow::OSShowWnd()
00518 {
00519     CATASSERT(fWindow != 0, "Call CreateWnd instead.");
00520 
00521     ShowWindow(fWindow, SW_SHOW);   
00522     UpdateWindow(fWindow);   
00523     fVisible = true;
00524 }
00525 
00526 
00527 void CATWindow::OSHideWnd()
00528 {
00529     if (fWindow)
00530     {
00531         ShowWindow(fWindow,SW_HIDE);
00532     }
00533     fVisible = false;
00534 }
00535 
00536 void CATWindow::OSDestroyWnd(CATWND wnd)
00537 {
00538     if (wnd == 0)
00539     {
00540         if (fWindow != 0)
00541         {
00542             ::DestroyWindow(fWindow);
00543             fWindow = 0;
00544         }
00545     }
00546     else
00547     {
00548         ::DestroyWindow(wnd);
00549     }
00550 }
00551 
00552 void CATWindow::OSDraw(CATDRAWCONTEXT drawContext, CATRect* dirtyRect)
00553 {
00554     // Figure out our drawing rectangle
00555     CATRect drawRect(this->fRect); 
00556 
00557     if ((dirtyRect != 0) && (dirtyRect->Width() != 0) && (dirtyRect->Height() != 0))
00558     {
00559         drawRect = *dirtyRect;
00560     }
00561 
00562     // Copy over dirty area of image copy
00563     CleanBackground(&drawRect);   
00564 
00565     // Draw the normal controls to a copy of our image
00566     this->Draw(fImageCopy, drawRect);
00567 
00568 
00569     // Create a background device context for double buffering the draw
00570     HDC imageDC = CreateCompatibleDC(drawContext);  
00571 
00572     // Create a bitmap from the dirty part of our image
00573     // Create a 24-bit dib section we can modify...
00574     BITMAPINFO bmpInfo;   
00575     CATUInt8* bmpBits = 0;
00576     memset(&bmpInfo,0,sizeof(bmpInfo));
00577     
00578     bmpInfo.bmiHeader.biSize         = sizeof(BITMAPINFOHEADER);
00579     bmpInfo.bmiHeader.biPlanes       = 1;
00580     bmpInfo.bmiHeader.biWidth        = drawRect.Width();
00581     bmpInfo.bmiHeader.biHeight       = -drawRect.Height();
00582     bmpInfo.bmiHeader.biBitCount     = 24;
00583     bmpInfo.bmiHeader.biSizeImage    = 0;
00584     bmpInfo.bmiHeader.biCompression  = BI_RGB;
00585     
00586     HBITMAP imageBmp = CreateDIBSection(imageDC, &bmpInfo, DIB_RGB_COLORS, (void**)&bmpBits, 0, 0);
00587     
00588     CATASSERT(imageBmp != 0, "Failed to create DIB for window drawing.");
00589 
00590     CATInt32 widthBytes = (((drawRect.Width() *3) + 3) / 4 ) * 4;
00591 
00592     if (bmpBits != 0)
00593     {
00594         fImageCopy->CopyOutBGR( bmpBits,
00595                                 drawRect.left, 
00596                                 drawRect.top, 
00597                                 drawRect.Width(), 
00598                                 drawRect.Height(),
00599                                 widthBytes);
00600     }
00601 
00602     // Select it into context
00603     SelectObject(imageDC, imageBmp);      
00604 
00605     // Let controls that need a device context draw to the background device   
00606     SetViewportOrgEx(imageDC, -drawRect.left, -drawRect.top, 0);
00607     this->PostDraw(imageDC, drawRect);
00608     SetViewportOrgEx(imageDC, 0, 0, 0);
00609 
00610     // Exclude post-draw controls
00611     HRGN curRgn  = 0;
00612     HRGN tmpRgn  = 0;
00613     HRGN orgRgn  = 0;
00614     if (fPostRegion != 0)
00615     {       
00616         curRgn = CreateRectRgn( 0, 0, 0, 0);      
00617         orgRgn = CreateRectRgn( 0, 0, 0, 0);
00618         tmpRgn = CreateRectRgn( drawRect.left,
00619                                 drawRect.top,
00620                                 drawRect.right,
00621                                 drawRect.bottom);
00622 
00623         CombineRgn(curRgn,tmpRgn,fPostRegion,RGN_DIFF);     
00624         ::GetClipRgn(drawContext,orgRgn);
00625         SelectObject(drawContext,curRgn);       
00626 
00627     }
00628 
00629     // Blt our image into the background context
00630     // Using StretchBlt for halftoning.  It's slower, but looks *so*
00631     // much better.
00632     StretchBlt( drawContext,
00633                 drawRect.left,
00634                 drawRect.top,
00635                 drawRect.Width(), 
00636                 drawRect.Height(),
00637                 imageDC,
00638                 0,
00639                 0,
00640                 drawRect.Width(),
00641                 drawRect.Height(),
00642                 SRCCOPY);
00643 
00644     // Free DC and bitmap
00645     DeleteDC(imageDC);
00646     DeleteObject(imageBmp);
00647 
00648 
00649     // Restore regions
00650     if (curRgn != 0)
00651     {
00652         // Clean up
00653         SelectClipRgn(drawContext,orgRgn);
00654         DeleteObject(orgRgn);
00655         DeleteObject(tmpRgn);
00656         DeleteObject(curRgn);
00657     }
00658 
00659 }
00660 
00661 //---------------------------------------------------------------------------
00662 // Generate region from a series of rectangles for clipping.
00663 //---------------------------------------------------------------------------
00664 CATOSREGION CATWindow::OSGenRegion(CATStack<CATRect>& rectStack)
00665 {
00666     CATOSREGION newRgn = CreateRectRgn(0,0,0,0);
00667 
00668     CATRect curRect;
00669     while (CATSUCCEEDED(rectStack.Pop(curRect)))
00670     {
00671         CATOSREGION tmpRgn = ::CreateRectRgn(curRect.left, curRect.top, curRect.right, curRect.bottom);
00672         ::CombineRgn(newRgn,newRgn,tmpRgn,RGN_OR);
00673         ::DeleteObject(tmpRgn);
00674     }
00675 
00676     return newRgn;
00677 }
00678 //---------------------------------------------------------------------------
00679 //---------------------------------------------------------------------------
00680 void CATWindow::OSFreeRegion(CATOSREGION region)
00681 {
00682     if (region)
00683     {
00684         ::DeleteObject(region);
00685     }
00686 }
00687 //---------------------------------------------------------------------------
00688 void CATWindow::OSBeginMouseTrack()
00689 {
00690     SetCapture(this->fWindow);
00691 }
00692 //---------------------------------------------------------------------------
00693 void CATWindow::OSEndMouseTrack()
00694 {
00695     ReleaseCapture();
00696 }
00697 //---------------------------------------------------------------------------
00698 void CATWindow::OSSetMouse(const CATPOINT& point, CATCursor& cursor)
00699 {
00700     POINT pt;
00701     pt.x = point.x;
00702     pt.y = point.y;
00703     ::ClientToScreen(this->fWindow,&pt);
00704     ::SetCursorPos(pt.x,pt.y);
00705     if (cursor.GetType() == CATCURSOR_HIDE)
00706     {
00707         cursor.HideCursor();
00708     }
00709     else
00710     {
00711         cursor.ShowCursor();
00712     }   
00713 }
00714 //---------------------------------------------------------------------------
00715 void CATWindow::Update()
00716 {
00717     if (this->fVisible)
00718     {
00719         ::UpdateWindow(this->fWindow);
00720     }
00721 }
00722 
00723 //---------------------------------------------------------------------------
00724 void CATWindow::OSDrawCursor(CATDRAWCONTEXT context, const CATPOINT& point, CATCursor& cursor)
00725 {
00726     DrawIcon(   context,
00727         point.x,
00728         point.y,
00729         cursor.GetOSCursor());
00730 }
00731 
00732 void CATWindow::PostDrawText( const CATString&    text,
00733                               CATDRAWCONTEXT      context,
00734                               const CATRect&      textRect,
00735                               const CATRect&      dirtyRect,
00736                               const CATColor&     tColor,
00737                               const CATString&    fontName,
00738                               CATFloat32          fontSize,
00739                               bool                multiline,
00740                               CATColor*           bgColor,
00741                               bool                italics,
00742                               bool                centered,
00743                               bool                autoSize)
00744 {
00745     CATString filtered = CATControl::FilterGUIString(text);
00746 
00747     // Right now we're redrawing the entire string over itself when redrawing
00748     // any portion of it.  This isn't optimal - should create a clip region at
00749     // least.  However, we're in a ViewPort mode for the confiltered we're
00750     // passed, so be careful if this is implemented.
00751     CATRect drawRect;
00752     if (textRect.Intersect(dirtyRect, &drawRect))
00753     {      
00754         // Optimize - move this elsewhere so fonts are precreated!!!!
00755         HFONT font    = 0;
00756         HFONT oldFont = 0;
00757 
00758         if (!autoSize)
00759             font = this->OSGetFont(fontName,fontSize,false,italics);
00760         else
00761             font = this->AutoFontSize(filtered,                                     
00762                                       textRect,
00763                                       fontName,
00764                                       fontSize,
00765                                       false,
00766                                       italics);
00767 
00768         oldFont = (HFONT)::SelectObject(context,font);
00769 
00770 
00771         RECT rect = *(RECT*)(CATRECT*)&textRect;
00772 
00773         // Convert colors
00774         COLORREF textColor = RGB( tColor.r ,tColor.g, tColor.b);
00775 
00776         // Setup colors and background mode
00777         int oldMode       = ::SetBkMode(context,bgColor?OPAQUE:TRANSPARENT);
00778         if (bgColor != 0)
00779         {
00780             HBRUSH fillBrush = ::CreateSolidBrush(RGB(bgColor->r,bgColor->g,bgColor->b));
00781             ::FillRect(context,&rect,fillBrush);
00782             DeleteObject(fillBrush);
00783             ::SetBkColor(context,RGB(bgColor->r,bgColor->g,bgColor->b));
00784         }
00785 
00786         COLORREF oldColor = ::SetTextColor(context,textColor);
00787 
00788         // Select our font
00789 
00790         // Draw
00791         DWORD textStyle = DT_VCENTER | DT_END_ELLIPSIS | ((multiline)?DT_WORDBREAK:DT_SINGLELINE) ;
00792         if (centered)
00793         {
00794             textStyle |= DT_CENTER;
00795         }
00796         else
00797         {
00798             textStyle |= DT_LEFT;
00799         }
00800 
00801         // Fudge factor for readability
00802         rect.left += 2;
00803 
00804         ::DrawTextEx(context, filtered.GetUnicodeBuffer(), filtered.LengthCalc(), &rect, textStyle, NULL);
00805         filtered.ReleaseBuffer();
00806 
00807         // Restore the colors and background
00808         ::SetTextColor(context,oldColor);
00809         ::SetBkMode(context, oldMode);
00810 
00811         // Clean up font (see note!)
00812         if (oldFont != 0)
00813         {
00814             ::SelectObject(context,oldFont);
00815         }
00816 
00817         if (font != 0)
00818         {
00819             OSReleaseFont(font);
00820         }
00821 
00822     }
00823 }
00824 
00825 void CATWindow::OSSetFocus(CATWND window)
00826 {
00827     if (window == 0)
00828     {
00829         window = this->fWindow;
00830     }
00831     ::SetFocus(window);
00832 }
00833 
00834 // OSMoveWnd() moves and/or resizes the specified window (or the base window)
00835 // to the requested rectangle.
00836 // 
00837 // If window == 0, then the base window is used.
00838 // \param rect - new window rect
00839 // \param wnd - the window, or 0 for base
00840 void CATWindow::OSMoveWnd(const CATRect& rect, CATWND wnd)
00841 {
00842     if (wnd == 0)
00843     {
00844         wnd = this->fWindow;
00845     }
00846 
00847     HWND parent = 0;
00848     // IF we're a child window, we need to handle moving the parent, not us.
00849     if (fIsOverlapped)
00850     {
00851         RECT wndRect;
00852         CATRect absRect = GetRectAbs(true);
00853         POINT tl = {absRect.left, absRect.top};
00854         POINT br = {absRect.right, absRect.bottom};
00855 
00856         parent = ::GetParent(fWindow);
00857         ::ClientToScreen(fWindow,&tl);
00858         ::ClientToScreen(fWindow,&br);
00859         ::GetWindowRect(parent,&wndRect);
00860 
00861         wndRect.left   += (rect.left  - tl.x);
00862         wndRect.top    += (rect.top   - tl.y);
00863         wndRect.right  += (rect.right - br.x);
00864         wndRect.bottom += (rect.bottom - br.y);
00865 
00866         ::SetWindowPos(parent,0,wndRect.left,wndRect.top,wndRect.right - wndRect.left, wndRect.bottom - wndRect.top, SWP_NOZORDER);
00867 
00868     }
00869     else
00870     {           
00871         ::SetWindowPos(wnd,0,rect.left, rect.top, rect.Width(), rect.Height(),SWP_NOZORDER);      
00872     }
00873 }
00874 
00875 void CATWindow::CenterWindow(CATWindow* parent)
00876 {
00877     if (parent == 0)
00878     {
00879         return;
00880     }
00881 
00882     CATRect parRect;
00883     CATRect newRect;
00884 
00885     parRect = parent->OSGetWndRect();
00886     newRect = this->GetRect();
00887 
00888     ::AdjustWindowRect((RECT*)&parRect, parent->OSGetWindowStyle(), FALSE);
00889     ::AdjustWindowRect((RECT*)&newRect, OSGetWindowStyle(), FALSE);
00890 
00891     newRect.SetOrigin( parRect.left + (parRect.Width()  - newRect.Width())/2,
00892                        parRect.top  + (parRect.Height() - newRect.Height()) / 2);
00893 
00894     ::SetWindowPos(this->fWindow,0, newRect.left, newRect.top,0,0,SWP_NOSIZE|SWP_NOZORDER);
00895 }
00896 
00897 CATRect CATWindow::OSGetDockRect()
00898 {
00899     CATRect rect;
00900 
00901     if (fIsOverlapped)
00902     {
00903         HWND parent = ::GetParent(this->fWindow);
00904         RECT clientRect;
00905         ::GetClientRect(parent,&clientRect);
00906         POINT tl;
00907         tl.x        = clientRect.left;
00908         tl.y        = clientRect.top;
00909         ::ClientToScreen(parent,&tl);
00910         rect.left   = tl.x;
00911         rect.top    = tl.y;
00912         rect.right  = tl.x + (clientRect.right - clientRect.left);     
00913         rect.bottom = tl.y + (clientRect.bottom - clientRect.top);
00914     }
00915     else
00916     {  
00917         CATRect absRect = GetRectAbs(true);
00918         RECT ourRect;
00919         SetRect(&ourRect,absRect.left, absRect.top, absRect.right, absRect.bottom);
00920         HMONITOR monitor = MonitorFromRect(&ourRect,MONITOR_DEFAULTTONEAREST);
00921         MONITORINFO monInfo;
00922         monInfo.cbSize = sizeof(monInfo);
00923         GetMonitorInfo(monitor, &monInfo);
00924         rect.Set(monInfo.rcWork.left, monInfo.rcWork.top, monInfo.rcWork.right, monInfo.rcWork.bottom);
00925     }
00926 
00927     return rect;
00928 }
00929 
00930 CATRect CATWindow::OSGetWndRect()
00931 {
00932     RECT wRect;
00933     
00934     GetWindowRect(this->fWindow,&wRect);
00935 
00936     return CATRect( wRect.left, 
00937                     wRect.top, 
00938                     wRect.right, 
00939                     wRect.bottom);
00940 }
00941 
00942 
00943 /// OSWndToScreen() converts x/y coordinates from within the window to screen
00944 /// coordinates.
00945 /// \param x - x position to convert
00946 /// \param y - y position to convert
00947 void CATWindow::OSWndToScreen( CATInt32& x, CATInt32& y)
00948 {
00949     POINT point;
00950     point.x = x;
00951     point.y = y;
00952     ::ClientToScreen(this->fWindow, &point);
00953     x = point.x;
00954     y = point.y;
00955 }
00956 
00957 /// OSScreenToWnd() converts x/y coordinates from within the screen to within
00958 /// the window.
00959 /// \param x - x position to convert
00960 /// \param y - y position to convert
00961 void CATWindow::OSScreenToWnd( CATInt32& x, CATInt32& y)
00962 {
00963     POINT point;
00964     point.x = x;
00965     point.y = y;
00966     ::ScreenToClient(this->fWindow, &point);
00967     x = point.x;
00968     y = point.y;
00969 }
00970 
00971 void CATWindow::OSSetCursor()
00972 {
00973     ::SetCursor(fCursor.GetOSCursor());
00974 }
00975 
00976 void CATWindow::OSSetCursor(CATCursor& cursor)
00977 {
00978     ::SetCursor(cursor.GetOSCursor());
00979     if (cursor.GetType() == CATCURSOR_HIDE)
00980     {
00981         cursor.HideCursor();
00982     }
00983     else
00984     {
00985         cursor.ShowCursor();
00986     }   
00987 }
00988 
00989 void CATWindow::OSMinimize()
00990 {
00991     ::ShowWindow(this->fWindow, SW_MINIMIZE);
00992 }
00993 
00994 void CATWindow::OSMaximize()
00995 {
00996     if ((this->fSizeable == true) && (fMaximized == false))
00997     {
00998         ::ShowWindow(this->fWindow, SW_MAXIMIZE);
00999         fMaximized = true;
01000     }
01001     else
01002     {
01003         ::ShowWindow(this->fWindow, SW_RESTORE);
01004         fMaximized = false;
01005     }
01006 }
01007 
01008 void CATWindow::SetActive()
01009 {
01010     ::SetActiveWindow(fWindow);
01011 }
01012 
01013 void CATWindow::OSShowToolTip(CATControl* curControl, const CATPOINT& point)
01014 {  
01015     if (fCurTool != 0)
01016     {
01017         if (curControl == fCurTool)
01018             return;
01019 
01020         OSHideToolTip();
01021     }
01022 
01023 
01024 
01025     if (fToolTip)
01026     {
01027         this->fCurTool = curControl;
01028 
01029         CATInt32 xOff = 0;
01030         CATInt32 yOff = 20;
01031         // Lots of work to find the position - should precalc this on
01032         // cursor changes...
01033         {
01034             CURSORINFO cursorInfo;
01035             ICONINFO   iconInfo;
01036 
01037             memset(&cursorInfo,0,sizeof(cursorInfo));
01038             memset(&iconInfo,0,sizeof(iconInfo));
01039             cursorInfo.cbSize = sizeof(cursorInfo);      
01040 
01041             if ( (::GetCursorInfo(&cursorInfo)) && (GetIconInfo(cursorInfo.hCursor,&iconInfo)))
01042             {   
01043                 if (iconInfo.hbmMask)
01044                 {
01045                     BITMAP bmpInfo;
01046                     ::GetObject( iconInfo.hbmMask, sizeof(bmpInfo), &bmpInfo );
01047 
01048                     if (iconInfo.hbmColor)
01049                     {
01050                         yOff = bmpInfo.bmHeight - iconInfo.yHotspot + 1;
01051                     }
01052                     else
01053                     {
01054                         yOff = (bmpInfo.bmHeight/2) - iconInfo.yHotspot + 1;
01055                     }
01056                 }
01057 
01058 
01059                 // Clean up bitmaps - we don't need them.
01060                 if (iconInfo.hbmColor)
01061                 {
01062                     DeleteObject(iconInfo.hbmColor);
01063                     iconInfo.hbmColor = 0;
01064                 }
01065 
01066                 if (iconInfo.hbmMask)
01067                 {
01068                     DeleteObject(iconInfo.hbmMask);
01069                     iconInfo.hbmMask = 0;
01070                 }
01071             }
01072         }
01073 
01074 
01075         // Reposition the tip
01076         fLastTipPos.x = point.x + xOff; // + 10;      
01077         fLastTipPos.y = point.y + yOff; // + 10;
01078         ::ClientToScreen(this->fWindow, (POINT*)(CATPOINT*)&fLastTipPos);
01079 
01080         ::SendMessage(fToolTip,TTM_TRACKPOSITION,0,(LPARAM)MAKELONG(fLastTipPos.x,fLastTipPos.y));
01081 
01082 
01083         // Update text
01084         OSUpdateToolTip();
01085 
01086         // Display it
01087         TOOLINFO ti;
01088         ti.uFlags   = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
01089         ti.cbSize   = sizeof(TOOLINFO);
01090         ti.hwnd     = this->OSGetWnd();
01091         ti.uId      = (DWORD)this->OSGetWnd();
01092         ti.hinst    = gApp->GetInstance();
01093         // Display it
01094         ::SendMessage(fToolTip,TTM_TRACKACTIVATE,(WPARAM)TRUE, (DWORD)&ti);
01095     }
01096 }
01097 
01098 void CATWindow::OSHideToolTip()
01099 {
01100     if (fCurTool != 0)
01101     {
01102         // Deactivate tooltip
01103         TOOLINFO ti;
01104         ti.uFlags   = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
01105         ti.cbSize   = sizeof(TOOLINFO);
01106         ti.hwnd     = this->OSGetWnd();
01107         ti.uId      = (DWORD)this->OSGetWnd();
01108         ti.hinst    = gApp->GetInstance();
01109         ::SendMessage(fToolTip,TTM_TRACKACTIVATE,(WPARAM)FALSE, (DWORD)&ti);
01110 
01111         fCurTool = 0;
01112     }
01113 }
01114 
01115 void CATWindow::OSUpdateToolTip()
01116 {
01117     if ((fToolTip) && (fCurTool))
01118     {
01119         CATString curText = fCurTool->GetHint();
01120         if (curText != fLastTipText)
01121         {      
01122             fLastTipText = curText;
01123             // Change text to value
01124             TOOLINFO ti;
01125             ti.uFlags   = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
01126             ti.cbSize   = sizeof(TOOLINFO);
01127             ti.hwnd     = this->OSGetWnd();
01128             ti.uId      = (DWORD)this->OSGetWnd();
01129             ti.hinst    = gApp->GetInstance();
01130 
01131             // Update string
01132             ti.lpszText = curText.GetUnicodeBuffer();
01133             ::SendMessage(fToolTip,TTM_UPDATETIPTEXT,0,(DWORD)&ti);
01134             curText.ReleaseBuffer();        
01135 
01136             ::SendMessage(fToolTip,TTM_UPDATE,0,0);
01137         }
01138     }
01139 }
01140 
01141 void CATWindow::OSBuildToolTips()
01142 {
01143     // Create the ToolTip control.
01144     if (fToolTip == 0)
01145     {
01146         fToolTip = ::CreateWindow(
01147                                     TOOLTIPS_CLASS, 
01148                                     TEXT(""),
01149                                     WS_POPUP,
01150                                     CW_USEDEFAULT, 
01151                                     CW_USEDEFAULT,
01152                                     CW_USEDEFAULT, 
01153                                     CW_USEDEFAULT,
01154                                     NULL, 
01155                                     NULL, 
01156                                     gApp->GetInstance(),
01157                                     NULL);
01158 
01159         TOOLINFO ti;
01160         ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
01161         ti.cbSize = sizeof(TOOLINFO);
01162         ti.hwnd   = this->OSGetWnd();
01163         ti.uId    = (DWORD)this->OSGetWnd();
01164         ti.hinst = gApp->GetInstance();
01165         ti.lpszText    = L"";
01166         ti.rect.left   = 0;
01167         ti.rect.top    = 0;
01168         ti.rect.right  = fRect.Width();
01169         ti.rect.bottom = fRect.Height();
01170         ::SendMessage(fToolTip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
01171 
01172         ::SendMessage(fToolTip, TTM_SETTIPBKCOLOR,   (DWORD)RGB(fToolTipBg.r,fToolTipBg.g,fToolTipBg.b),0);
01173         ::SendMessage(fToolTip, TTM_SETTIPTEXTCOLOR, (DWORD)RGB(fToolTipFore.r,fToolTipFore.g,fToolTipFore.b),0);
01174     }        
01175 }
01176 
01177 void CATWindow::SetTrackMouse(CATWND hwnd)
01178 {
01179     TRACKMOUSEEVENT eventTrack;
01180     memset(&eventTrack,0,sizeof(eventTrack));
01181     eventTrack.hwndTrack = hwnd;
01182     eventTrack.cbSize    = sizeof(eventTrack);
01183     eventTrack.dwFlags   = TME_QUERY;
01184     if (!TrackMouseEvent(&eventTrack))
01185     {
01186         CATASSERT(false,"TrackMouseEvent() failed.");
01187     }
01188     eventTrack.dwHoverTime = kTOOLTIPHOVERTIME;
01189     eventTrack.hwndTrack = hwnd;
01190     eventTrack.dwFlags   |= TME_HOVER | TME_LEAVE;
01191     if (!TrackMouseEvent(&eventTrack))
01192     {
01193         CATASSERT(false,"TrackMouseEvent() failed.");
01194     }
01195 }
01196 
01197 CATUInt32 CATWindow::OSGetWindowStyle()
01198 {
01199     CATUInt32 style = 0;
01200     if (fIsOverlapped)
01201     {
01202         style = WS_CHILD | WS_CLIPSIBLINGS;
01203     }
01204     else if (fCaptionBar)
01205     {
01206         style = WS_POPUPWINDOW | WS_CAPTION | WS_CLIPCHILDREN | WS_MINIMIZEBOX;
01207 
01208         if (fSizeable)
01209         {      
01210             style |= WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME;
01211         }
01212     }
01213     else
01214     {
01215         style = WS_POPUPWINDOW;   
01216 
01217         if (fSizeable)
01218         {
01219             style |= WS_THICKFRAME;
01220         }
01221     }
01222 
01223 
01224     return style;
01225 }
01226 
01227 
01228 CATFONT CATWindow::OSGetFont(  const CATString& fontName,
01229                                 CATFloat32      fontSize,
01230                                 bool            bold,
01231                                 bool            italic,
01232                                 bool            underlined)
01233 {
01234     CATFONT font = 0;
01235 
01236     HDC context = ::GetDC(this->fWindow);   
01237     if (fontName.IsEmpty() == false)
01238     {
01239         font = CreateFont(
01240                             -MulDiv((int)fontSize, GetDeviceCaps(context, LOGPIXELSY), 72),
01241                             0,
01242                             0,
01243                             0,
01244                             bold?FW_BOLD:FW_NORMAL,
01245                             italic?TRUE:FALSE, //italic
01246                             underlined?TRUE:FALSE, //underline
01247                             FALSE, //strike
01248                             ANSI_CHARSET, // charset
01249                             OUT_DEFAULT_PRECIS,
01250                             CLIP_DEFAULT_PRECIS,
01251                             DEFAULT_QUALITY,
01252                             DEFAULT_PITCH,
01253                             fontName);         
01254 
01255         // Kludge to force parameters for font even if used on screen DC
01256         HFONT oldFont = (HFONT)SelectObject(context,font);
01257         ::SelectObject(context,oldFont);
01258     }
01259     else
01260     {
01261         font = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);         
01262     }
01263 
01264     ::ReleaseDC(fWindow,context);
01265     return font;
01266 }
01267 
01268 CATFONT CATWindow::AutoFontSize(   const CATString& text,
01269                                    CATRect          rect,
01270                                    const CATString& fontName,
01271                                    CATFloat32       fontSize,
01272                                    bool             bold,
01273                                    bool             italic,
01274                                    bool             underlined)
01275 {
01276     // Ugh... implement later.
01277     CATFONT font = OSGetFont(fontName,fontSize,bold,italic,underlined);
01278     return font;
01279 }
01280 
01281 
01282 void CATWindow::OSReleaseFont( CATFONT& font)
01283 {
01284     ::DeleteObject(font);
01285     font = 0;
01286 }
01287 
01288 void CATWindow::PostEventNotification()
01289 {
01290     ::PostMessage( this->OSGetWnd(), CATWM_EVENTPOSTED, 0, 0);
01291 }
01292 
01293 void CATWindow::SetWindowTimer  (CATFloat32 frequencyHz)
01294 {
01295     CATUInt32 msec = (CATUInt32)(1000.0f / frequencyHz);
01296     ::SetTimer(this->OSGetWnd(), CATWM_UPDATETIMER, msec, 0);
01297 }
01298 
01299 void CATWindow::KillWindowTimer()
01300 {
01301     ::KillTimer(this->OSGetWnd(), CATWM_UPDATETIMER);
01302 }
01303 
01304 CATWND CATWindow::GetBaseWindow()
01305 {
01306     if (this->fIsOverlapped == false)
01307     {
01308         return this->OSGetWnd();
01309     }
01310 
01311     HWND rootWnd = this->OSGetWnd();
01312     while (rootWnd != 0)
01313     {
01314         if (::GetWindowLong(rootWnd, GWL_STYLE) & WS_CAPTION)
01315         {
01316             // Found caption bar - could be MDI or what-not, but it's our base
01317             return rootWnd;
01318         }
01319 
01320         if (!::GetParent(rootWnd))
01321             return rootWnd;
01322 
01323         rootWnd = ::GetParent(rootWnd);
01324     }
01325 
01326     // Hit null parent... just return our own window.
01327     return OSGetWnd();
01328 }
01329 
01330 unsigned int _stdcall CATWindow::OSCmdThread(void *param)
01331 {
01332     CATWindow* wnd = (CATWindow*)param;
01333     if (wnd != 0)
01334     {
01335         wnd->ThreadedCmdThread();
01336     }
01337     return 0;
01338 }
01339 
01340 void CATWindow::OSStartCmdThread()
01341 {
01342     unsigned int threadId = 0;
01343     fCmdThread = (void*)_beginthreadex(0,0,OSCmdThread,this,0,&threadId);
01344 }
01345 
01346 void CATWindow::OSWaitOnCmdThread()
01347 {   
01348     if (!fCmdThread)
01349     {
01350         return;
01351     }
01352 
01353     fExitThread = true;
01354     fThreadedCmdLock.Wait();
01355     CATTRACE("Posting exit for window");
01356     fThreadedCmdSignal.Fire();
01357     fThreadedCmdLock.Release();
01358 
01359     if (WAIT_OBJECT_0 != ::WaitForSingleObject((HANDLE)fCmdThread,5000))
01360     {
01361         ::TerminateThread((HANDLE)fCmdThread,-1);
01362         CATASSERT(false,"WARNING: had to terminate window command thread!");
01363     }
01364 
01365     CloseHandle((HANDLE)fCmdThread);
01366     fExitThread = false;
01367 
01368     fCmdThread = 0;
01369 }
01370 
01371 LRESULT CATWindow::OSOnSize(   HWND hwnd,
01372                                UINT uMsg,
01373                                WPARAM wParam,
01374                                LPARAM lParam,
01375                                bool& handled)
01376 {
01377     CATRect newRect;
01378     RECT wndRect;
01379     ::GetClientRect(hwnd, (RECT*)(CATRECT*)&newRect);
01380     ::GetWindowRect(hwnd,&wndRect);
01381 
01382     CATRect testRect = newRect;
01383 
01384     // If we're a top-level window, adjust for borders.
01385     if (fIsOverlapped == false)
01386     {
01387         ::AdjustWindowRect( (RECT*)(CATRECT*)&testRect,  OSGetWindowStyle(), FALSE);
01388     }
01389 
01390     CATInt32 xOff = newRect.left - testRect.left;
01391     CATInt32 yOff = newRect.top - testRect.top;
01392 
01393     newRect.Offset(wndRect.left + xOff,wndRect.top + yOff);
01394 
01395     CATPOINT offsetPt;
01396     offsetPt.x = newRect.left;
01397     offsetPt.y = newRect.top;
01398     OnMove(offsetPt);
01399 
01400     newRect.ZeroOrigin();
01401     OnSize(newRect);
01402     handled = true;
01403     return 0;
01404 }
01405 LRESULT CATWindow::OSOnKeyUp(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01406 {
01407     CATMODKEY modKey = GetModifierKeys();
01408 
01409     switch (wParam)
01410     {
01411         case VK_SPACE:    OnKeyUp(CATKeystroke(0x20,CATKEY_NONE,modKey)); break;
01412         case VK_LEFT:     OnKeyUp(CATKeystroke(0,CATKEY_LEFT,   modKey)); break; 
01413         case VK_RIGHT:    OnKeyUp(CATKeystroke(0,CATKEY_RIGHT,  modKey)); break;                    
01414         case VK_UP:       OnKeyUp(CATKeystroke(0,CATKEY_UP,     modKey)); break;                    
01415         case VK_DOWN:     OnKeyUp(CATKeystroke(0,CATKEY_DOWN,   modKey)); break;                    
01416         case VK_HOME:     OnKeyUp(CATKeystroke(0,CATKEY_HOME,   modKey)); break;                    
01417         case VK_END:      OnKeyUp(CATKeystroke(0,CATKEY_END,    modKey)); break;
01418         case VK_NEXT:     OnKeyUp(CATKeystroke(0,CATKEY_NEXT,   modKey)); break;
01419         case VK_PRIOR:    OnKeyUp(CATKeystroke(0,CATKEY_PRIOR,  modKey)); break;
01420         case VK_INSERT:   OnKeyUp(CATKeystroke(0,CATKEY_INSERT, modKey)); break;
01421         case VK_DELETE:   OnKeyUp(CATKeystroke(0,CATKEY_DELETE, modKey)); break;
01422         case VK_F2:       OnKeyUp(CATKeystroke(0,CATKEY_F2,     modKey)); break;
01423         case VK_F3:       OnKeyUp(CATKeystroke(0,CATKEY_F3,     modKey)); break;
01424         case VK_F4:       OnKeyUp(CATKeystroke(0,CATKEY_F4,     modKey)); break;
01425         case VK_F5:       OnKeyUp(CATKeystroke(0,CATKEY_F5,     modKey)); break;
01426         case VK_F6:       OnKeyUp(CATKeystroke(0,CATKEY_F6,     modKey)); break;
01427         case VK_F7:       OnKeyUp(CATKeystroke(0,CATKEY_F7,     modKey)); break;
01428         case VK_F8:       OnKeyUp(CATKeystroke(0,CATKEY_F8,     modKey)); break;
01429         case VK_F9:       OnKeyUp(CATKeystroke(0,CATKEY_F9,     modKey)); break;
01430         case VK_F10:      OnKeyUp(CATKeystroke(0,CATKEY_F10,    modKey)); break;
01431         case VK_F11:      OnKeyUp(CATKeystroke(0,CATKEY_F11,    modKey)); break;
01432         case VK_F12:      OnKeyUp(CATKeystroke(0,CATKEY_F12,    modKey)); break;
01433     }            
01434     return 0;
01435 }
01436 
01437 LRESULT CATWindow::OSOnKeyDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01438 {
01439     LRESULT lRes = 0;
01440     CATTRACE("Got WM_KEYDOWN...");
01441     CATMODKEY modKey = GetModifierKeys();
01442 
01443     switch (wParam)
01444     {
01445         // Special purpose keys               
01446         case VK_F1:       
01447             OnHelp();
01448             break;
01449 
01450         // Tab for focus selection
01451         case VK_TAB:
01452             {
01453                 if (modKey & CATMODKEY_SHIFT)
01454                 {
01455                     SetFocusPrev();
01456                 }
01457                 else
01458                 {
01459                     SetFocusNext();
01460                 }
01461                 lRes = 1;
01462                 handled = true;
01463             }
01464             break;                      
01465         case VK_ESCAPE:
01466             if (fFocusControl != 0)
01467             {
01468                 KillFocus();
01469                 lRes = 1;
01470                 handled = true;
01471             }
01472             break;
01473         
01474         case VK_LEFT:
01475         case VK_UP:
01476                 SetFocusPrev();
01477                 lRes = 1;
01478                 handled = true;
01479                 break;
01480 
01481         case VK_RIGHT:
01482         case VK_DOWN:
01483                 SetFocusNext();
01484                 lRes = 1;
01485                 handled = true;
01486                 break;
01487 
01488         // "standard" special keystrokes
01489         case VK_HOME:     OnKeyDown(CATKeystroke(0,CATKEY_HOME,modKey));    break;                    
01490         case VK_END:      OnKeyDown(CATKeystroke(0,CATKEY_END,modKey));     break;
01491         case VK_NEXT:     OnKeyDown(CATKeystroke(0,CATKEY_NEXT,modKey));    break;
01492         case VK_PRIOR:    OnKeyDown(CATKeystroke(0,CATKEY_PRIOR,modKey));   break;
01493         case VK_INSERT:   OnKeyDown(CATKeystroke(0,CATKEY_INSERT,modKey));  break;
01494         case VK_DELETE:   OnKeyDown(CATKeystroke(0,CATKEY_DELETE,modKey));  break;
01495         case VK_F2:       OnKeyDown(CATKeystroke(0,CATKEY_F2,modKey));      break;
01496         case VK_F3:       OnKeyDown(CATKeystroke(0,CATKEY_F3,modKey));      break;
01497         case VK_F4:       OnKeyDown(CATKeystroke(0,CATKEY_F4,modKey));      break;
01498         case VK_F5:       OnKeyDown(CATKeystroke(0,CATKEY_F5,modKey));      break;
01499         case VK_F6:       OnKeyDown(CATKeystroke(0,CATKEY_F6,modKey));      break;
01500         case VK_F7:       OnKeyDown(CATKeystroke(0,CATKEY_F7,modKey));      break;
01501         case VK_F8:       OnKeyDown(CATKeystroke(0,CATKEY_F8,modKey));      break;
01502         case VK_F9:       OnKeyDown(CATKeystroke(0,CATKEY_F9,modKey));      break;
01503         case VK_F10:      OnKeyDown(CATKeystroke(0,CATKEY_F10,modKey));     break;
01504         case VK_F11:      OnKeyDown(CATKeystroke(0,CATKEY_F11,modKey));     break;
01505         case VK_F12:      OnKeyDown(CATKeystroke(0,CATKEY_F12,modKey));     break;
01506         
01507         // Keys we track up/down for
01508         default:          OnKeyDown(CATKeystroke(wParam,CATKEY_NONE,modKey)); lRes=1;handled=true;break;
01509     }            
01510     return lRes;
01511 }
01512 
01513 
01514 LRESULT CATWindow::OSOnMinMax(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01515 {
01516     MINMAXINFO* minMax = (MINMAXINFO*)lParam;
01517     CATInt32 minx,miny,maxx,maxy;
01518     GetMinMax(minx,miny,maxx,maxy);
01519     // Argh... we've got minmax for client rect, now
01520     // translate to window rect coordinates....
01521     CATUInt32 style = OSGetWindowStyle();
01522 
01523     RECT minRect;
01524     RECT maxRect;
01525     ::SetRect(&maxRect,0,0,maxx,maxy);
01526     ::SetRect(&minRect,0,0,minx,miny);
01527     AdjustWindowRect(&minRect,style,FALSE);
01528     AdjustWindowRect(&maxRect,style,FALSE);
01529     if (minx != 0)
01530         minx = minRect.right - minRect.left;
01531     if (miny != 0)
01532         miny = minRect.bottom - minRect.top;
01533     if (maxx != 0)
01534         maxx = maxRect.right - maxRect.left;
01535     if (maxy != 0)
01536         maxy = maxRect.bottom - maxRect.top;
01537 
01538 
01539 
01540     // Okay, NOW we have the right info
01541     if (minx != 0)
01542         minMax->ptMinTrackSize.x = minx;
01543     if (miny != 0)
01544         minMax->ptMinTrackSize.y = miny;
01545 
01546     if (maxx != 0)
01547         minMax->ptMaxTrackSize.x = maxx;
01548 
01549     if (maxy != 0)
01550         minMax->ptMaxTrackSize.y = maxy;
01551 
01552     handled = true;
01553     return 0;
01554 }
01555 
01556 
01557 LRESULT CATWindow::OSDropFiles(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01558 {
01559     CATUInt32 numFiles = ::DragQueryFile( (HDROP)wParam, -1, 0, 0);
01560 
01561     for (CATUInt32 curFile = 0; curFile < numFiles; curFile++)
01562     {
01563         CATWChar filenameBuf[_MAX_PATH+1];
01564         if (0 != ::DragQueryFile( (HDROP)wParam, curFile, filenameBuf, _MAX_PATH))
01565         {
01566             CATResult result;
01567             if (CATFAILED(result = OnDropFile(filenameBuf)))
01568             {
01569                 DisplayError(result);
01570             }
01571         }
01572     }
01573     handled = true;
01574     return 0;
01575 }            
01576 
01577 LRESULT CATWindow::OSGetControlColors(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01578 {
01579     LRESULT lRes = 0;
01580     HWND ctlhwnd = (HWND)lParam;
01581     CATControlWnd* theControl = 0;
01582     if ( (theControl = GetCtlWnd(ctlhwnd)) != 0 )
01583     {
01584         HDC dc = (HDC)wParam;
01585 
01586         CATColor bgColor = theControl->GetColorBack();
01587         CATColor fgColor = theControl->GetColorFore();
01588 
01589         SetBkColor((HDC)wParam, RGB(bgColor.r, bgColor.g, bgColor.b));
01590         SetTextColor((HDC)wParam, RGB(fgColor.r, fgColor.g, fgColor.b));
01591         lRes = (LRESULT)theControl->GetBGBrush();
01592         handled  = true;
01593     }
01594     return lRes;
01595 }
01596 
01597 LRESULT CATWindow::OSOnAppCmd(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01598 {
01599     LRESULT lRes = 0;
01600     switch (GET_APPCOMMAND_LPARAM(lParam))
01601     {
01602         case APPCOMMAND_BROWSER_BACKWARD:
01603         case APPCOMMAND_BROWSER_FORWARD:
01604         case APPCOMMAND_BROWSER_HOME:
01605         case APPCOMMAND_BROWSER_REFRESH:
01606         case APPCOMMAND_BROWSER_SEARCH:
01607         case APPCOMMAND_BROWSER_STOP:
01608         case APPCOMMAND_MEDIA_NEXTTRACK:
01609         case APPCOMMAND_MEDIA_PREVIOUSTRACK:
01610         case APPCOMMAND_MEDIA_PLAY_PAUSE:
01611         case APPCOMMAND_MEDIA_STOP:
01612         case APPCOMMAND_TREBLE_DOWN:
01613         case APPCOMMAND_TREBLE_UP:
01614         case APPCOMMAND_BASS_DOWN:
01615         case APPCOMMAND_BASS_UP:
01616         case APPCOMMAND_VOLUME_DOWN:
01617         case APPCOMMAND_VOLUME_UP:
01618         case APPCOMMAND_VOLUME_MUTE:     
01619             break;       
01620     }  
01621     return lRes;
01622 }
01623 
01624 LRESULT CATWindow::OSOnPaint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01625 {
01626     // Get the update region prior to calling BeginPaint,
01627     // as BeginPaint destroys it.
01628     HRGN updateRgn      = ::CreateRectRgn(0,0,0,0);
01629     int rgnType         = ::GetUpdateRgn(hwnd,updateRgn,FALSE);
01630     HPALETTE appPalette = (HPALETTE)(UINT_PTR)GetWindowLong(hwnd,0);
01631 
01632     // Call get paint anyway - we don't want to mess
01633     // with validating stuff ourselves.
01634     PAINTSTRUCT ps;
01635     HDC drawContext = ::BeginPaint(hwnd,&ps);
01636 
01637     // Default rect to draw everything...
01638     CATRect defaultRect = fRect;
01639 
01640 
01641     SetStretchBltMode (drawContext,HALFTONE);
01642     SetBrushOrgEx     (drawContext,0,0,NULL);
01643     SelectPalette     (drawContext,appPalette,FALSE);
01644     RealizePalette    (drawContext);
01645 
01646     DWORD rgnSize = ::GetRegionData(updateRgn,0,0);
01647     if (rgnSize == 0)
01648     {        
01649         OSDraw(drawContext, &defaultRect);
01650     }
01651     else
01652     {
01653         RGNDATA* rgnData = (RGNDATA*)new char[rgnSize];
01654         if (rgnData != 0)
01655         {
01656             memset(rgnData,0,rgnSize);
01657             rgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
01658             if ((::GetRegionData(updateRgn,rgnSize,rgnData) == rgnSize) && (rgnData->rdh.nCount > 0))
01659             {                        
01660                 // Got the data... now draw.
01661                 for (CATUInt32 i = 0; i < rgnData->rdh.nCount; i++)
01662                 {                              
01663                     RECT curRect = *(RECT*)(rgnData->Buffer + i * sizeof(RECT));
01664                     CATRect dirtyRect;
01665                     dirtyRect.Set(curRect.left, curRect.top, curRect.right, curRect.bottom);                           
01666                     OSDraw(drawContext, &dirtyRect);                     
01667                 }                                                         
01668             }
01669             else
01670             {
01671                 // No rects in region - draw it all it's a full paint.                
01672                 OSDraw(drawContext, &defaultRect);
01673             }
01674             delete [] (char*)rgnData;
01675         }
01676     }
01677     ::DeleteObject(updateRgn);                  
01678     ::ReleaseDC(hwnd, drawContext);
01679     ::EndPaint(hwnd,&ps);               
01680     //  Validate the window
01681     // ::ValidateRect(hwnd,0);
01682     handled  = true;    
01683     return 0;
01684 }
01685 
01686 LRESULT CATWindow::OSOnMeasureItem(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01687 {
01688     LRESULT lRes = 0;
01689     LPMEASUREITEMSTRUCT measureInfo = (LPMEASUREITEMSTRUCT)lParam;
01690     switch (measureInfo->CtlType)
01691     {
01692         case ODT_MENU:
01693             {
01694                 // Owner drawn menus... the itemData will be a CATMENUITEM structure from CATMenu.h
01695                 CATMENUITEM* menuItem = (CATMENUITEM*)measureInfo->itemData;
01696                 if (menuItem != 0)
01697                 {
01698                     CATMenu* menu = menuItem->BaseMenu;
01699                     if (menu)
01700                     {
01701                         menu->OSOnMeasureItem(  menuItem, 
01702                                                 (CATUInt32&)measureInfo->itemWidth, 
01703                                                 (CATUInt32&)measureInfo->itemHeight);
01704                         lRes     = TRUE;
01705                         handled  = true;
01706                     }
01707                 }
01708             }
01709             break;
01710 
01711         case ODT_LISTBOX:
01712             {
01713                 // Owner drawn menus... the itemData will be a CATLISTINFO structure from CATListBox.h
01714                 CATLISTINFO* listItem = (CATLISTINFO*)measureInfo->itemData;
01715                 if (listItem != 0)
01716                 {
01717                     CATListBox* listBox = listItem->BaseListBox;
01718                     
01719                     if (listBox)
01720                     {
01721                         listBox->OSOnMeasureItem( listItem, 
01722                                                  (CATUInt32&)measureInfo->itemWidth, 
01723                                                  (CATUInt32&)measureInfo->itemHeight);
01724                         lRes     = TRUE;
01725                         handled  = true;
01726                     }
01727                 }
01728             }
01729             break;
01730         case ODT_COMBOBOX:
01731         case ODT_LISTVIEW:
01732             break;
01733     }
01734 
01735     return lRes;
01736 }
01737 
01738 LRESULT CATWindow::OSOnDrawItem(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01739 {
01740     LRESULT lRes = 0;
01741     LPDRAWITEMSTRUCT drawInfo = (LPDRAWITEMSTRUCT)lParam;
01742     switch (drawInfo->CtlType)
01743     {
01744         case ODT_MENU:
01745             {                        
01746                 CATMENUITEM* menuItem = (CATMENUITEM*)drawInfo->itemData;
01747                 if (menuItem != 0)
01748                 {
01749                     CATMenu* menu = menuItem->BaseMenu;
01750                     if (menu)
01751                     {
01752                         menu->OSOnDrawItem(  menuItem, 
01753                                             (drawInfo->itemState & ODS_SELECTED)?true:false,
01754                                             drawInfo->hDC,
01755                                             CATRect(drawInfo->rcItem.left, 
01756                                             drawInfo->rcItem.top, 
01757                                             drawInfo->rcItem.right, 
01758                                             drawInfo->rcItem.bottom));
01759                         lRes     = TRUE;
01760                         handled  = true;
01761                     }
01762                 }
01763             }
01764             break;
01765 
01766         case ODT_LISTBOX:
01767             {                        
01768                 CATLISTINFO* listItem = (CATLISTINFO*)drawInfo->itemData;
01769                 if (listItem != 0)
01770                 {
01771                     CATListBox* listBox = listItem->BaseListBox;
01772                     if (listBox)
01773                     {
01774                         listBox->OSOnDrawItem(  listItem, 
01775                                                 (drawInfo->itemState & ODS_SELECTED)?true:false,
01776                                                 drawInfo->hDC,
01777                                                 CATRect(drawInfo->rcItem.left, 
01778                                                 drawInfo->rcItem.top, 
01779                                                 drawInfo->rcItem.right, 
01780                                                 drawInfo->rcItem.bottom));
01781                         lRes     = TRUE;
01782                         handled  = true;
01783                     }
01784                 }
01785             }
01786             break;
01787 
01788         case ODT_BUTTON:
01789         case ODT_COMBOBOX:
01790         case ODT_LISTVIEW:
01791         case ODT_STATIC:
01792         case ODT_TAB:
01793             break;
01794     }
01795 
01796     return lRes;
01797 }
01798 
01799 LRESULT CATWindow::OSGetObject(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& handled)
01800 {
01801     LRESULT lRes = 0;
01802     /* Don't enable until CATAccessible is finished...
01803     DWORD dwObjId = lParam;
01804     
01805     switch (dwObjId)
01806     {
01807         case OBJID_CLIENT:            
01808             IAccessible *pAcc = this->GetAccessible();
01809             lRes = LresultFromObject(IID_IAccessible, wParam, (IUnknown*)pAcc);
01810             handled = true;
01811             break;
01812     }    
01813     */
01814     return lRes;
01815 }

Generated on Mon Feb 11 04:09:58 2008 for Game Accessibility Suite by doxygen 1.5.4