core/vgui/impl/mfc/vgui_mfc_adaptor.cxx
Go to the documentation of this file.
00001 // This is core/vgui/impl/mfc/vgui_mfc_adaptor.cxx
00002 #include "vgui_mfc_adaptor.h"
00003 //:
00004 // \file
00005 // \author RRG, Oxford University
00006 // \brief  See vgui_mfc_adaptor.h for a description of this file.
00007 //
00008 // \verbatim
00009 //  Modifications
00010 //   06-AUG-2002 K.Y.McGaul - Changed key returned by CTRL events.
00011 //   04-OCT-2002 K.Y.McGaul - Use event.set_key() to set key, this makes sure
00012 //                            the key stroke is always lower case.
00013 //                          - Set event.ascii_char to be the actual key stroke.
00014 // \endverbatim
00015 
00016 #include <vcl_iostream.h>
00017 #include <vcl_cstring.h>
00018 
00019 #include <vgui/vgui_gl.h>
00020 #include <vgui/vgui_event.h>
00021 #include <vgui/vgui_popup_params.h>
00022 #include <vgui/vgui_macro.h>
00023 #include <vgui/impl/mfc/vgui_mfc_utils.h>
00024 #include <vgui/impl/mfc/vgui_mfc_mainfrm.h>
00025 
00026 static bool debug = false;
00027 extern bool vgui_mfc_use_bitmap;
00028 /////////////////////////////////////////////////////////////////////////////
00029 // vgui_mfc_adaptor
00030 
00031 vgui_menu vgui_mfc_adaptor::last_popup;
00032 IMPLEMENT_DYNCREATE(vgui_mfc_adaptor, CView)
00033 
00034 
00035 //: Constructor.
00036 vgui_mfc_adaptor::vgui_mfc_adaptor( )
00037   : m_pDC(0), m_pDC_default_bitmap(0),
00038     m_pDC_aux(0), m_pDC_aux_default_bitmap(0),
00039     win_(0),
00040     redraw_posted_(true),
00041     overlay_redraw_posted_(true),
00042     idle_request_posted_(false)
00043 {
00044   if (vgui_mfc_use_bitmap)
00045     // kym - double buffering is not available with
00046     // acceleration (it crashes windows).
00047     set_double_buffering(false);
00048 
00049   // If m_pCWnd is not set (using setup_adaptor) assume we use the main window:
00050   m_pCWnd = 0;
00051   hOldDC = 0;
00052   hOldRC = 0;
00053 }
00054 
00055 //: Destructor.
00056 //  kym - moved stuff here from OnDestroy because OnDestroy seems to only be
00057 //  called when the main window is deleted.
00058 vgui_mfc_adaptor::~vgui_mfc_adaptor()
00059 {
00060   CView::OnDestroy();
00061 
00062   // This call makes the current RC not current
00063   if (FALSE == ::wglMakeCurrent(hOldDC, hOldRC))
00064     ::AfxMessageBox("wglMakeCurrent failed" );
00065 
00066   // Delete the RC
00067   if ( m_hRC && (FALSE == ::wglDeleteContext( m_hRC )) )
00068   {
00069     ::AfxMessageBox("wglDeleteContext failed.");
00070   }
00071 
00072   // Release the device context:
00073   HDC m_hgldc = ::GetDC(m_hWnd);
00074   ::ReleaseDC(m_hWnd, m_hgldc);
00075 
00076   // Delete the DC
00077   if ( m_pDC )
00078   {
00079     if ( m_pDC_default_bitmap )
00080     {
00081       HBITMAP hBmp = (HBITMAP)::SelectObject( m_pDC->GetSafeHdc(), m_pDC_default_bitmap );
00082       if (hBmp == 0)
00083         ::AfxMessageBox("SelectObject with old HBITMAP failed.");
00084       else
00085         ::DeleteObject(hBmp);
00086     }
00087     delete m_pDC;
00088   }
00089   if ( m_pDC_aux )
00090   {
00091     if ( m_pDC_aux_default_bitmap )
00092     {
00093       HBITMAP hBmp = (HBITMAP)::SelectObject( m_pDC_aux->GetSafeHdc(), m_pDC_aux_default_bitmap );
00094       if (hBmp == 0)
00095         ::AfxMessageBox("SelectObject with old HBITMAP failed.");
00096       else
00097         ::DeleteObject(hBmp);
00098     }
00099     delete m_pDC_aux;
00100   }
00101 }
00102 
00103 BEGIN_MESSAGE_MAP(vgui_mfc_adaptor, CView)
00104   ON_WM_CREATE()
00105   ON_WM_DESTROY()
00106   ON_WM_ERASEBKGND()
00107   ON_WM_SIZE()
00108   ON_WM_KEYDOWN()
00109   ON_WM_KEYUP()
00110   ON_WM_LBUTTONDOWN()
00111   ON_WM_LBUTTONUP()
00112   ON_WM_MOUSEMOVE()
00113   ON_WM_RBUTTONDOWN()
00114   ON_WM_RBUTTONUP()
00115   ON_WM_MOUSEWHEEL()
00116   ON_WM_MBUTTONDOWN()
00117   ON_WM_MBUTTONUP()
00118   ON_WM_PAINT()
00119 END_MESSAGE_MAP()
00120 
00121 
00122 // 0. vgui_adaptor methods
00123 //------------------------
00124 
00125 //: MFC implementation of vgui_adaptor function - redraws overlay buffer.
00126 void vgui_mfc_adaptor::post_overlay_redraw()
00127 {
00128   if (!overlay_redraw_posted_)
00129   {
00130     CWnd* wnd;
00131     if (m_pCWnd != 0)
00132       wnd = m_pCWnd;
00133     else
00134       wnd = AfxGetApp()->GetMainWnd();
00135     if (wnd)
00136       wnd->Invalidate(FALSE);
00137   }
00138   overlay_redraw_posted_ = true;
00139 }
00140 
00141 //: MFC implementation of vgui_adaptor function - redraws rendering area.
00142 void vgui_mfc_adaptor::post_redraw()
00143 {
00144   if (!redraw_posted_)
00145   {
00146     //CWnd *wnd = AfxGetApp()->GetMainWnd();
00147     CWnd* wnd;
00148     if (m_pCWnd != 0)
00149       wnd = m_pCWnd;
00150     else
00151       wnd = AfxGetApp()->GetMainWnd();
00152     if (wnd)
00153       wnd->Invalidate(FALSE);
00154   }
00155   redraw_posted_ = true;
00156 }
00157 
00158 //: MFC implementation of vgui_adaptor function - make this the current GL rendering context.
00159 void vgui_mfc_adaptor::make_current()
00160 {
00161   ::wglMakeCurrent( m_pDC->GetSafeHdc(), m_hRC );
00162 }
00163 
00164 //: MFC implementation of vgui_adaptor function - swap buffers if using double buffering.
00165 void vgui_mfc_adaptor::swap_buffers()
00166 {
00167   if ( !vgui_mfc_use_bitmap )
00168     SwapBuffers(m_pDC->m_hDC);
00169 }
00170 
00171 //: Change the default popup menu to the given one (not yet implemented).
00172 void vgui_mfc_adaptor::set_default_popup(vgui_menu)
00173 {
00174   vcl_cerr << "vgui_mfc_adaptor::set_default_popup\n";
00175 }
00176 
00177 //: Return the default popup menu (not yet implemented).
00178 vgui_menu vgui_mfc_adaptor::get_popup()
00179 {
00180   vcl_cerr<< "vgui_mfc_adaptor::get_popup\n";
00181   return vgui_menu();
00182 }
00183 
00184 //: If your adaptor is not in the main window of the application call this function.
00185 //  The first parameter tells it which window this adaptor is associated with,
00186 //  the other parameters are so we can go back to our old rendering context.
00187 void vgui_mfc_adaptor::setup_adaptor(CWnd* this_cwnd, HDC oldDC, HGLRC oldContext)
00188 {
00189   m_pCWnd = this_cwnd;
00190   hOldDC = oldDC;
00191   hOldRC = oldContext;
00192 }
00193 
00194 #ifdef _DEBUG
00195 void vgui_mfc_adaptor::AssertValid() const
00196 {
00197   CView::AssertValid();
00198 }
00199 
00200 void vgui_mfc_adaptor::Dump(CDumpContext& dc) const
00201 {
00202   CView::Dump(dc);
00203 }
00204 #endif //_DEBUG
00205 
00206 //: Called by MFC before the creation of the window attached to this object.
00207 BOOL vgui_mfc_adaptor::PreCreateWindow(CREATESTRUCT& cs)
00208 {
00209   // TODO: Add your specialized code here and/or call the base class
00210   // An OpenGL window must be created with the following
00211   // flags and must not include CS_PARENTDC for the
00212   // class style.
00213 
00214   cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
00215 
00216   return CView::PreCreateWindow(cs);
00217 }
00218 
00219 //: Called by MFC when the application requests the creation of a window.
00220 //  This function must return 0 to continue the creation of the CWind
00221 //  object, returning -1 destroys the window.
00222 int vgui_mfc_adaptor::OnCreate(LPCREATESTRUCT lpCreateStruct)
00223 {
00224   if (CView::OnCreate(lpCreateStruct) == -1)
00225     return -1;
00226 
00227   // TODO: Add your specialized creation code here
00228 
00229   if (vgui_mfc_use_bitmap) {
00230     create_bitmap( 1, 1, m_pDC, m_pDC_default_bitmap );
00231     create_bitmap( 1, 1, m_pDC_aux, m_pDC_aux_default_bitmap );
00232     set_double_buffering(false);
00233   } else {
00234     m_pDC = new CClientDC(this);
00235   }
00236 
00237   if ( NULL == m_pDC ) // failure to get DC
00238   {
00239     ::AfxMessageBox("Couldn't get a valid DC.");
00240     return FALSE;
00241   }
00242 
00243   if ( vgui_mfc_use_bitmap )
00244     m_hRC = setup_for_gl( m_pDC,
00245                           PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL );
00246   else
00247     m_hRC = setup_for_gl( m_pDC,
00248                           PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER );
00249 
00250   post_redraw();
00251 
00252   return 0;
00253 }
00254 
00255 
00256 HGLRC vgui_mfc_adaptor::setup_for_gl( CDC* pDC, DWORD dwFlags )
00257 {
00258   PIXELFORMATDESCRIPTOR pfd;
00259   ZeroMemory( &pfd, sizeof( pfd ) );
00260   pfd.nSize = sizeof( pfd );
00261   pfd.nVersion = 1;
00262   pfd.dwFlags = dwFlags;
00263   pfd.iPixelType = PFD_TYPE_RGBA;
00264   pfd.cColorBits = 24;
00265   pfd.cDepthBits = 16;
00266   pfd.iLayerType = PFD_MAIN_PLANE;
00267 
00268   int pixelformat = ChoosePixelFormat( pDC->GetSafeHdc(), &pfd );
00269 
00270   if (0 == pixelformat) {
00271     ::AfxMessageBox("ChoosePixelFormat failed.");
00272     vcl_cerr<<"Error code:"<<GetLastError();
00273     return 0;
00274   }
00275   if ( FALSE == SetPixelFormat( pDC->GetSafeHdc(), pixelformat, &pfd ) )
00276   {
00277     AfxMessageBox("SetPixelFormat failed.");
00278     vcl_cerr<<"Error code:"<<GetLastError();
00279     return 0;
00280   }
00281 
00282   HGLRC glrc = wglCreateContext( pDC->GetSafeHdc() );
00283   if ( 0 == glrc )
00284   {
00285     AfxMessageBox("wglCreateContext failed.");
00286     return 0;
00287   }
00288 
00289   if ( FALSE == wglMakeCurrent( pDC->GetSafeHdc(), glrc ) )
00290   {
00291     AfxMessageBox("wglMakeCurrent failed.");
00292     return 0;
00293   }
00294 
00295   // specify black as clear color
00296   glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
00297   // specify the back of the buffer as clear depth
00298   glClearDepth( 1.0f );
00299   // enable depth testing
00300   glEnable( GL_DEPTH_TEST );
00301 
00302   vgui_macro_report_errors;
00303 
00304   return glrc;
00305 }
00306 
00307 
00308 void vgui_mfc_adaptor::create_bitmap( int cx, int cy,
00309                                       CDC*& pDC,
00310                                       HBITMAP& defaultBitmapForDC )
00311 {
00312   BITMAPINFOHEADER bih;
00313   ZeroMemory( &bih, sizeof(bih) );
00314 
00315   bih.biSize = sizeof(bih);
00316   bih.biWidth = cx;
00317   bih.biHeight = cy;
00318   bih.biPlanes = 1;
00319   bih.biBitCount = 24;
00320   bih.biCompression = BI_RGB;
00321 
00322   if ( !pDC ){
00323     pDC = new CDC();
00324     pDC->CreateCompatibleDC(NULL);
00325   }
00326 
00327   void *buffer;
00328   HBITMAP hbmp = CreateDIBSection( pDC->GetSafeHdc(),
00329                                    (BITMAPINFO *)&bih,
00330                                    DIB_RGB_COLORS,
00331                                    &buffer,
00332                                    NULL,
00333                                    0 );
00334   if ( !hbmp ) {
00335     AfxMessageBox( "Failed to create bitmap" );
00336     return;
00337   }
00338   pDC->SetStretchBltMode(COLORONCOLOR);
00339   HBITMAP old_hbmp = (HBITMAP)SelectObject( pDC->GetSafeHdc(), hbmp );
00340   if (old_hbmp == 0)
00341   {
00342     ::AfxMessageBox( "Failed to select bitmap into DC" );
00343     return;
00344   }
00345 
00346   if (defaultBitmapForDC == 0)
00347     defaultBitmapForDC = old_hbmp;
00348   else
00349     if ( !DeleteObject(old_hbmp) ) // Our object - delete it
00350     {
00351       ::AfxMessageBox( "Failed to delete old bitmap" );
00352       return;
00353     }
00354 }
00355 
00356 
00357 //: Called by MFC when the main window has been destroyed.
00358 void vgui_mfc_adaptor::OnDestroy()
00359 {
00360   // kym - moved stuff to the destructor because this only seems
00361   // to be called when the main window is destroyed.
00362 }
00363 
00364 //: Called by MFC when the background needs erasing.
00365 //  For example this would be called if the window was resized.
00366 BOOL vgui_mfc_adaptor::OnEraseBkgnd(CDC* pDC)
00367 {
00368   // don't clear - gl will do it.
00369   return TRUE;
00370 }
00371 
00372 //: Redraws the OpenGL area.
00373 void vgui_mfc_adaptor::service_redraws()
00374 {
00375   if ( redraw_posted_ )
00376   {
00377     vgui_macro_report_errors;
00378     this->make_current();
00379     dispatch_to_tableau(vgui_event(vgui_DRAW));
00380     vgui_macro_report_errors;
00381     redraw_posted_ = false;
00382     aux_dc_valid_ = false;
00383   }
00384 
00385   if ( overlay_redraw_posted_ )
00386   {
00387     this->make_current();
00388 
00389     if ( vgui_mfc_use_bitmap )
00390     {
00391       if ( aux_dc_valid_ ) {
00392         // copy aux buffer to gl buffer
00393         m_pDC->BitBlt( 0, 0, m_width, m_height, m_pDC_aux, 0, 0, SRCCOPY );
00394       } else {
00395         // copy gl buffer to aux buffer
00396         m_pDC_aux->BitBlt( 0, 0, m_width, m_height, m_pDC, 0, 0, SRCCOPY );
00397         aux_dc_valid_ = true;
00398       }
00399     }
00400     else
00401     {
00402       // Determine we if just did a redraw (aux_dc_valid_==false iff
00403       // just did a redraw).
00404       //
00405       if ( aux_dc_valid_ ) {
00406         // Nope. Do a redraw to delete the previous overlay
00407         dispatch_to_tableau( vgui_event(vgui_DRAW) );
00408       } else {
00409         // Yep. But next time we won't have...
00410         aux_dc_valid_ = true;
00411       }
00412     }
00413 
00414     vgui_macro_report_errors;
00415     dispatch_to_tableau(vgui_event(vgui_DRAW_OVERLAY));
00416     vgui_macro_report_errors;
00417 
00418     overlay_redraw_posted_ = false;
00419   }
00420 
00421   if ( vgui_mfc_use_bitmap )
00422   {
00423     CWnd* wnd;
00424     if (m_pCWnd)
00425       wnd = m_pCWnd;
00426     else {
00427       CWinApp* ap = AfxGetApp();
00428       if (ap)
00429         wnd = ap->GetMainWnd();
00430       else return;
00431     }
00432     CDC *win_dc = wnd->GetDC();
00433     RECT r;
00434     wnd->GetClientRect(&r);
00435     win_dc->BitBlt(0,0,r.right,r.bottom,m_pDC,0,0,SRCCOPY);
00436     wnd->ReleaseDC(win_dc);
00437   }
00438 
00439   swap_buffers();
00440 }
00441 
00442 //: Sets timer to dispatch WM_TIMER event to a mainframe every time milliseconds
00443 void vgui_mfc_adaptor::post_timer(float tm,int id)
00444 {
00445   CWnd* wnd;
00446   if (m_pCWnd)
00447     wnd = m_pCWnd;
00448   else
00449     wnd = AfxGetApp()->GetMainWnd();
00450   wnd->SetTimer(id,tm,NULL);
00451 }
00452 
00453 //: Stop timer to dispatch WM_TIME event
00454 void vgui_mfc_adaptor::kill_timer(int id)
00455 {
00456   CWnd* wnd;
00457   if (m_pCWnd)
00458     wnd = m_pCWnd;
00459   else
00460     wnd = AfxGetApp()->GetMainWnd();
00461   wnd->KillTimer(id);
00462 }
00463 
00464 //: Called by MFC when a draw event is required - overridden to draw this view.
00465 void vgui_mfc_adaptor::OnDraw(CDC* pDC)
00466 {
00467   if (debug)
00468     vcl_cerr << "OnDraw\n";
00469   // post_redraw();
00470 
00471   service_redraws();
00472   // CView::OnDraw(pDC);
00473 }
00474 
00475 //: MFC implementation of vgui_adaptor function - redraw everything now!
00476 void vgui_mfc_adaptor::draw()
00477 {
00478   post_redraw();
00479   service_redraws();
00480 }
00481 
00482 bool vgui_mfc_adaptor::do_idle()
00483 {
00484   if ( idle_request_posted_ )
00485     idle_request_posted_ =  dispatch_to_tableau( vgui_event( vgui_IDLE ) );
00486   return idle_request_posted_;
00487 }
00488 
00489 
00490 //: Called by MFC when the application requests part of the window is redrawn.
00491 void vgui_mfc_adaptor::OnPaint()
00492 {
00493   CView::OnPaint();
00494 }
00495 
00496 //: Called by MFC when the application is resized.
00497 void vgui_mfc_adaptor::OnSize(UINT nType, int cx, int cy)
00498 {
00499   CView::OnSize(nType, cx, cy);
00500 
00501   m_width = cx;
00502   m_height = cy;
00503 
00504   if ( cx != 0 && cy != 0 && vgui_mfc_use_bitmap )
00505   {
00506     // create a new GL bitmap and aux bitmap to match the new window
00507     // size.
00508     create_bitmap( cx, cy, m_pDC, m_pDC_default_bitmap );
00509     m_hRC = setup_for_gl( m_pDC,
00510                           PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL );
00511     create_bitmap( cx, cy, m_pDC_aux, m_pDC_aux_default_bitmap );
00512   }
00513   dispatch_to_tableau(vgui_RESHAPE);
00514   post_redraw();
00515 }
00516 
00517 //: Convert MFC key character into an int suitable for vgui.
00518 void mfc_key(UINT nChar, UINT nFlags, int *the_key, int *the_ascii_char)
00519 {
00520   if (nFlags & 256)
00521   {
00522     // Extended code
00523     switch (nChar)
00524     {
00525       case VK_NEXT:
00526         *the_key = vgui_PAGE_DOWN;
00527         *the_ascii_char = vgui_PAGE_DOWN;
00528         return;
00529       case VK_PRIOR:
00530         *the_key = vgui_PAGE_UP;
00531         *the_ascii_char = vgui_PAGE_UP;
00532         return;
00533       case VK_HOME:
00534         *the_key = vgui_HOME;
00535         *the_ascii_char = vgui_HOME;
00536         return;
00537       case VK_END:
00538         *the_key = vgui_END;
00539         *the_ascii_char = vgui_END;
00540         return;
00541       case VK_LEFT:
00542         *the_key = vgui_CURSOR_LEFT;
00543         *the_ascii_char = vgui_CURSOR_LEFT;
00544         return;
00545       case VK_UP:
00546         *the_key = vgui_CURSOR_UP;
00547         *the_ascii_char = vgui_CURSOR_UP;
00548         return;
00549       case VK_RIGHT:
00550         *the_key = vgui_CURSOR_RIGHT;
00551         *the_ascii_char = vgui_CURSOR_RIGHT;
00552         return;
00553       case VK_DOWN:
00554         *the_key = vgui_CURSOR_DOWN;
00555         *the_ascii_char = vgui_CURSOR_DOWN;
00556         return;
00557       default:
00558         *the_key = vgui_key(0);
00559         *the_ascii_char = vgui_key(0);
00560         return;
00561     }
00562   }
00563   else if (nChar >= VK_F1 && nChar <= VK_F12)
00564   {
00565     *the_key = *the_ascii_char = vgui_F1 + (nChar - VK_F1);
00566   }
00567   else
00568   {
00569     unsigned short buf[1024];
00570     unsigned char lpKeyState[256];
00571     vcl_memset(lpKeyState, 0, 256);
00572     vcl_memset(buf, 0, 256);
00573 
00574     int is_ok = ToAscii(nChar, nFlags & 0xff, lpKeyState, buf, 0);
00575     if (is_ok == 1)
00576       *the_key = buf[0];
00577     else
00578       *the_key = nChar;
00579 
00580     // Add modifiers to character:
00581     lpKeyState[VK_SHIFT] = GetKeyState(VK_SHIFT);
00582     lpKeyState[VK_CONTROL] = GetKeyState(VK_CONTROL);
00583 
00584     is_ok = ToAscii(nChar, nFlags & 0xff, lpKeyState, buf, 0);
00585     if (is_ok == 1)
00586       *the_ascii_char = buf[0];
00587     else
00588       *the_ascii_char = nChar;
00589   }
00590 }
00591 
00592 //: Create the corresponding vgui_event from an MFC event.
00593 vgui_event vgui_mfc_adaptor::generate_vgui_event(UINT nChar, UINT nRepCnt, UINT nFlags, vgui_event_type evttype)
00594 {
00595   vgui_event evt(evttype);
00596   if (GetKeyState(VK_SHIFT) & 0x8000)
00597     evt.modifier = vgui_SHIFT;
00598   if (GetKeyState(VK_CONTROL) & 0x8000)
00599     evt.modifier = vgui_CTRL;
00600   if (GetKeyState(VK_MENU) & 0x8000)
00601     evt.modifier = vgui_ALT;
00602   // kym - VK_MENU (alt key) doesn't seem to reach here - it is used
00603   // by the menu, so, it seems, there will be no vgui_ALT events for MFC.
00604 
00605   int the_key, the_ascii_char;
00606   mfc_key(nChar, nFlags, &the_key, &the_ascii_char);
00607   evt.set_key( vgui_key(the_key) );
00608   evt.ascii_char = vgui_key(the_ascii_char);
00609   return evt;
00610 }
00611 
00612 //: Called by MFC when a key is pressed inside the application.
00613 void vgui_mfc_adaptor::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
00614 {
00615    // Ignore Ctrl and Shift pressed alone:
00616   if (nChar == VK_SHIFT || nChar == VK_CONTROL)
00617     return;
00618 
00619   dispatch_to_tableau(generate_vgui_event(nChar, nRepCnt, nFlags, vgui_KEY_PRESS));
00620   service_redraws();
00621 }
00622 
00623 //: Called by MFC when a key is released inside the application.
00624 void vgui_mfc_adaptor::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
00625 {
00626   // Ignore Ctrl and Shift pressed alone:
00627   if (nChar == VK_SHIFT || nChar == VK_CONTROL)
00628     return;
00629 
00630   dispatch_to_tableau(generate_vgui_event(nChar, nRepCnt, nFlags, vgui_KEY_RELEASE));
00631   service_redraws();
00632 }
00633 
00634 //: Handles mouse press/release events.
00635 void vgui_mfc_adaptor::domouse(vgui_event_type et, UINT nFlags, CPoint point, vgui_button b)
00636 {
00637 #if 0
00638   vcl_cerr <<"vgui_mfc_adaptor::domouse: wo = "<< point.x<<", "<< point.y<<'\n';
00639 #endif
00640   // awf: BLETCH. This offset is consistent over resize, depth, screen position, machines,
00641   // and I can't find it... Sorry.
00642   point.x += 2;
00643   point.y += 2;
00644   // FIXME
00645 
00646   vgui_event e(et);
00647 
00648   e.button = b;
00649   if (nFlags & MK_LBUTTON) e.button = vgui_LEFT;
00650   if (nFlags & MK_MBUTTON) e.button = vgui_MIDDLE;
00651   if (nFlags & MK_RBUTTON) e.button = vgui_RIGHT;
00652   if (nFlags & MK_SHIFT)   e.modifier = vgui_modifier((int)e.modifier | vgui_SHIFT);
00653   if (nFlags & MK_CONTROL) e.modifier = vgui_modifier((int)e.modifier | vgui_CTRL);
00654   e.wx = point.x;
00655   e.wy = m_height - point.y;
00656   //: Deals with right popup menu
00657   if (e.modifier == mixin::popup_modifier  && e.button == mixin::popup_button)
00658   {
00659     vgui_popup_params params;
00660     params.x = point.x;
00661     params.y = point.y;
00662     last_popup = get_total_popup(params);
00663     CMenu *popup = vgui_mfc_utils::instance()->set_popup_menu(last_popup);
00664     //CWnd *wnd = AfxGetApp()->GetMainWnd();
00665     CWnd* wnd;
00666     if (m_pCWnd)
00667       wnd = m_pCWnd;
00668     else
00669       wnd = AfxGetApp()->GetMainWnd();
00670     //: 'point' is window coordinates whereas TrackPopup menu requires screen coordinates.
00671     // So translate them into screen coordinates
00672     ClientToScreen(&point);
00673     popup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,wnd);
00674     delete popup;
00675   }
00676   else
00677     dispatch_to_tableau(e);
00678 
00679   // Grabbing the mouse here causes an issue with code that runs
00680   // another instance of the event loop in response to the event (sent
00681   // by the dispatch_to_tableau call above).  An example if
00682   // vgui_rubberband_tableau, which, on a point add, could cause a
00683   // dialog to pop up.  In general, grabbing the mouse is a very
00684   // client specific thing, and we should probably not be doing it all
00685   // the time, as it is being done here.  If we want, we may consider
00686   // putting this in the interface.  However, given vgui's goals of
00687   // being a light & thin wrapper, I don't think that's a good idea.
00688   //
00689   // // Grab mouse?
00690   // {
00691   //   if (et == vgui_BUTTON_DOWN) {
00692   //     SetCapture();
00693   //   } else if (et != vgui_MOTION) {
00694   //     ReleaseCapture();
00695   //   }
00696   // }
00697 }
00698 
00699 //: Called by MFC when the left mouse button is pressed inside the application.
00700 void vgui_mfc_adaptor::OnLButtonDown(UINT nFlags, CPoint point)
00701 {
00702   domouse(vgui_BUTTON_DOWN, nFlags, point, vgui_LEFT);
00703 }
00704 
00705 //: Called by MFC when the left mouse button is released inside the application.
00706 void vgui_mfc_adaptor::OnLButtonUp(UINT nFlags, CPoint point)
00707 {
00708   domouse(vgui_BUTTON_UP, nFlags, point, vgui_LEFT);
00709 }
00710 
00711 //: Called by MFC when the middle mouse button is pressed inside the application.
00712 void vgui_mfc_adaptor::OnMButtonDown(UINT nFlags, CPoint point)
00713 {
00714   domouse(vgui_BUTTON_DOWN, nFlags, point, vgui_MIDDLE);
00715 }
00716 
00717 //: Called by MFC when the middle mouse button is released inside the application.
00718 void vgui_mfc_adaptor::OnMButtonUp(UINT nFlags, CPoint point)
00719 {
00720   domouse(vgui_BUTTON_UP, nFlags, point, vgui_MIDDLE);
00721 }
00722 
00723 //: Called by MFC when the right mouse button is pressed inside the application.
00724 void vgui_mfc_adaptor::OnRButtonDown(UINT nFlags, CPoint point)
00725 {
00726   domouse(vgui_BUTTON_DOWN, nFlags, point, vgui_RIGHT);
00727 }
00728 
00729 //: Called by MFC when the right mouse button is released inside the application.
00730 void vgui_mfc_adaptor::OnRButtonUp(UINT nFlags, CPoint point)
00731 {
00732   domouse(vgui_BUTTON_UP, nFlags, point, vgui_RIGHT);
00733 }
00734 
00735 //: Called by MFC when the mouse is moved inside the application.
00736 void vgui_mfc_adaptor::OnMouseMove(UINT nFlags, CPoint point)
00737 {
00738   domouse(vgui_MOTION, nFlags, point, vgui_BUTTON_NULL);
00739 }
00740 
00741 //: Called by MFC when a user rotates a mouse wheel.
00742 BOOL vgui_mfc_adaptor::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
00743 {
00744 #ifdef DEBUG
00745   vcl_cerr << "Mouse wheel events are not handled\n";
00746 #endif
00747   return FALSE;
00748 }
00749