Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/toolx/Windows/pixwin is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef toolx_Windows_pixwin
0005 #define toolx_Windows_pixwin
0006 
0007 #include <windows.h>
0008 #include <windowsx.h>
0009 #include <wingdi.h>
0010 
0011 #include <tools/sg/device_interactor>
0012 #include <tools/sg/keys>
0013 
0014 #include <string>
0015 
0016 #if defined(_MSC_VER) && _MSC_VER < 1900
0017 #elif defined(__MINGW32__)
0018 #else
0019 #define TOOLX_WINDOWS_TOUCH
0020 #endif
0021 
0022 namespace toolx {
0023 namespace Windows {
0024 
0025 #ifdef TOOLX_WINDOWS_TOUCH
0026 inline bool is_message_touch_event() {
0027   // from https://stackoverflow.com/questions/29857587/detect-if-wm-mousemove-is-caused-by-touch-pen.
0028   static const LONG_PTR c_SIGNATURE_MASK = 0xFFFFFF00;
0029   static const LONG_PTR c_MOUSEEVENTF_FROMTOUCH = 0xFF515700;
0030   LONG_PTR extraInfo = ::GetMessageExtraInfo();
0031   return ( ( extraInfo & c_SIGNATURE_MASK ) == c_MOUSEEVENTF_FROMTOUCH );
0032 }
0033 #endif
0034 
0035 class pixwin {
0036   static const std::string& s_class() {
0037     static const std::string s_v("toolx::Windows::pixwin");
0038     return s_v;
0039   }
0040   static void register_class(){
0041     static bool s_done = false; //not const, then not thread safe.
0042     if(!s_done) {
0043       WNDCLASS         wc;
0044       wc.style         = CS_HREDRAW | CS_VREDRAW;
0045       wc.lpfnWndProc   = (WNDPROC)proc;
0046       wc.cbClsExtra    = 0;
0047       wc.cbWndExtra    = 0;
0048       wc.hInstance     = ::GetModuleHandle(NULL);
0049       wc.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
0050       wc.hCursor       = LoadCursor(NULL,IDC_ARROW);
0051       wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
0052       wc.lpszMenuName  = (PTSTR)s_class().c_str();
0053       wc.lpszClassName = (PTSTR)s_class().c_str();
0054       ::RegisterClass(&wc);
0055       s_done = true;
0056     }
0057   }
0058 public:
0059   virtual void resize(unsigned int,unsigned int){}
0060   virtual void paint() {}
0061   virtual void close(){}
0062   
0063   virtual void left_button_up(unsigned int a_x,unsigned int a_y) {}
0064   virtual void left_button_down(unsigned int a_x,unsigned int a_y) {}
0065   virtual void mouse_move(unsigned int a_x,unsigned int a_y,bool) {}
0066 public:
0067   pixwin(HWND a_parent,unsigned int a_w,unsigned int a_h)
0068   :m_parent(a_parent)
0069   ,m_hwnd(0)
0070   ,m_touch_available(false)
0071   ,m_interactor(0)
0072   {
0073     register_class();
0074     m_hwnd = ::CreateWindow((PTSTR)s_class().c_str(),
0075                              NULL,
0076                              WS_CHILD | WS_VISIBLE,
0077                              0,0,
0078                              a_w,a_h,
0079                              m_parent,NULL,
0080                              GetWindowInstance(m_parent),
0081                              NULL);
0082     if(!m_hwnd) return;
0083     ::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
0084 
0085 #ifdef TOOLX_WINDOWS_TOUCH
0086    {BYTE digitizer_status = (BYTE)::GetSystemMetrics(SM_DIGITIZER);
0087     if((digitizer_status & (0x80 + 0x40)) == 0) {
0088       m_touch_available = false;
0089     } else {
0090       m_touch_available = true;
0091       if(!::RegisterTouchWindow(m_hwnd,0)) m_touch_available = false;
0092     }}
0093 #endif
0094 
0095   }
0096   virtual ~pixwin(){
0097     if(m_hwnd) {
0098       ::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
0099       ::DestroyWindow(m_hwnd);
0100       m_hwnd = 0;
0101     }
0102   }
0103 protected:
0104   pixwin(const pixwin& a_from)
0105   :m_parent(a_from.m_parent)
0106   ,m_hwnd(0)
0107   ,m_touch_available(a_from.m_touch_available)
0108   ,m_interactor(0)
0109   {
0110     if(!m_parent) return;
0111     register_class();
0112     RECT rect;
0113     ::GetClientRect(m_parent,&rect);
0114     m_hwnd = ::CreateWindow((PTSTR)s_class().c_str(),
0115                              NULL,
0116                              WS_CHILD | WS_VISIBLE,
0117                              0,0,
0118                              rect.right-rect.left,
0119                              rect.bottom-rect.top,
0120                              m_parent,NULL,
0121                              GetWindowInstance(m_parent),
0122                              NULL);
0123     if(!m_hwnd) return;
0124     ::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
0125 
0126 #ifdef TOOLX_WINDOWS_TOUCH
0127     if(a_from.m_touch_available) {
0128       if(!::RegisterTouchWindow(m_hwnd,0)) m_touch_available = false;
0129     }
0130 #endif
0131   }
0132 protected:
0133   pixwin& operator=(const pixwin&){return *this;}
0134 public:
0135   void set_client_area_size(unsigned int a_w,unsigned int a_h) {
0136     RECT rect;
0137     ::GetClientRect(m_hwnd,&rect);
0138     ::MoveWindow(m_hwnd,rect.left,rect.top,a_w,a_h,TRUE);
0139   }
0140   HWND hwnd() const {return m_hwnd;}
0141   void post_WM_PAINT() const {
0142     if(!m_hwnd) return;
0143     ::PostMessage(m_hwnd,WM_PAINT,(WPARAM)0,(LPARAM)0);
0144   }
0145   void send_WM_PAINT() const {
0146     if(!m_hwnd) return;
0147     ::SendMessage(m_hwnd,WM_PAINT,(WPARAM)0,(LPARAM)0);
0148   }
0149   void wm_paint() {paint();}
0150 public:
0151   void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} //we do not have ownership.
0152 protected:
0153   bool is_touch_event() {
0154 #ifdef TOOLX_WINDOWS_TOUCH
0155     if(!m_touch_available) return false;
0156     return is_message_touch_event();
0157 #else
0158     return false;
0159 #endif
0160   }
0161 protected:
0162   static LRESULT CALLBACK proc(HWND a_hwnd,UINT a_msg,WPARAM a_wparam,LPARAM a_lparam) {
0163     switch (a_msg) {
0164     case WM_SIZE:{
0165       int width = LOWORD(a_lparam);
0166       int height = HIWORD(a_lparam);
0167       pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0168       if(_this) {
0169         _this->resize(width,height);
0170       } else {
0171         // CreateWindow send a WM_SIZE but GWLP_USERDATA not yet set.
0172       }
0173     }return 0;
0174     case WM_PAINT:{
0175       pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0176       if(_this) _this->wm_paint();
0177     }return 0;
0178 
0179     case WM_KEYDOWN:{
0180       pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0181       if(_this) {
0182         if(_this->m_interactor) {
0183           tools::sg::key_down_event event(_this->convert_key(a_wparam));
0184           _this->m_interactor->key_press(event);
0185         }
0186       } 
0187     } return 0;
0188     case WM_KEYUP:{
0189       pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0190       if(_this) {
0191         if(_this->m_interactor) {
0192           tools::sg::key_up_event event(_this->convert_key(a_wparam));
0193           _this->m_interactor->key_release(event);
0194         }
0195       } 
0196     } return 0;
0197 
0198     case WM_LBUTTONDOWN:{
0199       pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0200       if(_this) {
0201         if(_this->m_interactor) {
0202           bool shift_modifier = ::GetKeyState(VK_SHIFT)  & 0x8000;
0203           bool control_modifier = ::GetKeyState(VK_CONTROL) & 0x8000;
0204           tools::sg::mouse_down_event event(LOWORD(a_lparam),HIWORD(a_lparam),shift_modifier,control_modifier);
0205           _this->m_interactor->mouse_press(event);
0206         } else {
0207           RECT rect;
0208           ::GetClientRect(a_hwnd,&rect);
0209           unsigned int h = rect.bottom-rect.top;
0210           if(!_this->is_touch_event()) _this->left_button_down(LOWORD(a_lparam),h-HIWORD(a_lparam));
0211         }
0212       }
0213     }return 0;
0214     case WM_LBUTTONUP:{
0215       pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0216       if(_this) {
0217         if(_this->m_interactor) {
0218           bool shift_modifier = ::GetKeyState(VK_SHIFT)  & 0x8000;
0219           bool control_modifier = ::GetKeyState(VK_CONTROL) & 0x8000;
0220           tools::sg::mouse_up_event event(LOWORD(a_lparam),HIWORD(a_lparam),shift_modifier,control_modifier);
0221           _this->m_interactor->mouse_release(event);
0222         } else {
0223           RECT rect;
0224           ::GetClientRect(a_hwnd,&rect);
0225           unsigned int h = rect.bottom-rect.top;
0226           if(!_this->is_touch_event()) _this->left_button_up(LOWORD(a_lparam),h-HIWORD(a_lparam));
0227         }
0228       }
0229     } return 0;
0230     case WM_MOUSEMOVE:{
0231       pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0232       if(_this) {
0233         WPARAM state = a_wparam;
0234         bool ldown = ((state & MK_LBUTTON)==MK_LBUTTON)?true:false;
0235         if(_this->m_interactor) {
0236           if(ldown) {
0237             bool shift_modifier = ::GetKeyState(VK_SHIFT)  & 0x8000;
0238             bool control_modifier = ::GetKeyState(VK_CONTROL) & 0x8000;
0239             tools::sg::mouse_move_event event(LOWORD(a_lparam),HIWORD(a_lparam),shift_modifier,control_modifier,0,0,false);
0240             _this->m_interactor->mouse_move(event);
0241           }
0242         } else {
0243           RECT rect;
0244           ::GetClientRect(a_hwnd,&rect);
0245           unsigned int h = rect.bottom-rect.top;
0246           if(!_this->is_touch_event()) _this->mouse_move(LOWORD(a_lparam),h-HIWORD(a_lparam),ldown);
0247         }
0248       }
0249 
0250     }return 0;
0251     
0252     case WM_MOUSEWHEEL:{
0253       pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0254       if(_this) {
0255         if(_this->m_interactor) {
0256           bool shift_modifier = ::GetKeyState(VK_SHIFT)  & 0x8000;
0257           bool control_modifier = ::GetKeyState(VK_CONTROL) & 0x8000;
0258           POINT p;
0259           p.x = LOWORD(a_lparam);
0260           p.y = HIWORD(a_lparam);
0261           if(!::ScreenToClient(a_hwnd,&p)) {}
0262           tools::sg::wheel_rotate_event event(GET_WHEEL_DELTA_WPARAM(a_wparam),int(p.x),int(p.y),shift_modifier,control_modifier);
0263           _this->m_interactor->wheel_rotate(event);
0264         }         
0265       } 
0266     } return 0;
0267       
0268 #ifdef TOOLX_WINDOWS_TOUCH
0269     case WM_TOUCH:{
0270       pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0271       if(_this && _this->m_touch_available) {
0272         RECT rect;
0273         ::GetClientRect(a_hwnd,&rect);
0274         unsigned int h = rect.bottom-rect.top;
0275 
0276         unsigned int num_inputs = (int)a_wparam;
0277         TOUCHINPUT* ti = new TOUCHINPUT[num_inputs];
0278         POINT p;
0279         if(::GetTouchInputInfo((HTOUCHINPUT)a_lparam,num_inputs,ti,sizeof(TOUCHINPUT))) {
0280           for(unsigned int i=0;i<num_inputs; ++i) {
0281             p.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
0282             p.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
0283             if(!::ScreenToClient(a_hwnd,&p)) {}
0284             if(ti[i].dwFlags & TOUCHEVENTF_DOWN) {
0285               _this->left_button_down(p.x,h-p.y);
0286             } else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
0287               _this->left_button_up(p.x,h-p.y);
0288             } else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
0289               bool ldown = true; //we assume that a TOUCHEVENT_DOWN had been done.
0290               _this->mouse_move(p.x,h-p.y,ldown);
0291             }
0292           }
0293         }
0294         ::CloseTouchInputHandle((HTOUCHINPUT)a_lparam);
0295         delete [] ti;
0296       }
0297     }return 0;
0298 #endif //TOOLX_WINDOWS_TOUCH
0299     case WM_DESTROY:wm__destroy(a_hwnd);return 0;
0300     }
0301     return (DefWindowProc(a_hwnd,a_msg,a_wparam,a_lparam));
0302   }
0303   static bool SetWindowPixelFormat(HDC a_HDC){
0304     PIXELFORMATDESCRIPTOR pfd;
0305     pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
0306     pfd.nVersion = 1;
0307     pfd.dwFlags =
0308       PFD_DRAW_TO_WINDOW |
0309       PFD_SUPPORT_OPENGL |
0310       PFD_DOUBLEBUFFER |
0311       PFD_STEREO_DONTCARE;
0312     pfd.iPixelType = PFD_TYPE_RGBA;
0313     pfd.cColorBits = 32;
0314     pfd.cRedBits = 8;
0315     pfd.cRedShift = 16;
0316     pfd.cGreenBits = 8;
0317     pfd.cGreenShift = 8;
0318     pfd.cBlueBits = 8;
0319     pfd.cBlueShift = 0;
0320     pfd.cAlphaBits = 0;
0321     pfd.cAlphaShift = 0;
0322     pfd.cAccumBits = 64;
0323     pfd.cAccumRedBits = 16;
0324     pfd.cAccumGreenBits = 16;
0325     pfd.cAccumBlueBits = 16;
0326     pfd.cAccumAlphaBits = 0;
0327     pfd.cDepthBits = 32;
0328     pfd.cStencilBits = 8;
0329     pfd.cAuxBuffers = 0;
0330     pfd.iLayerType = PFD_MAIN_PLANE;
0331     pfd.bReserved = 0;
0332     pfd.dwLayerMask = 0;
0333     pfd.dwVisibleMask = 0;
0334     pfd.dwDamageMask = 0;
0335 
0336     int pixelIndex = ::ChoosePixelFormat(a_HDC,&pfd);
0337     if (pixelIndex==0) {
0338       // Let's choose a default index.
0339       pixelIndex = 1;
0340       if (::DescribePixelFormat(a_HDC,
0341                                 pixelIndex,
0342                                 sizeof(PIXELFORMATDESCRIPTOR),
0343                                 &pfd)==0) {
0344         return false;
0345       }
0346     }
0347 
0348     if (::SetPixelFormat(a_HDC,pixelIndex,&pfd)==FALSE) return false;
0349 
0350     return true;
0351   }
0352   static void wm__destroy(HWND a_hwnd) {
0353     pixwin* _this = (pixwin*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0354     if(_this) { //How to be sure that we have a pixwin* ???
0355       _this->close();
0356       if(_this->m_hwnd!=a_hwnd) {
0357       }
0358       _this->m_hwnd = 0;
0359     }
0360     ::SetWindowLongPtr(a_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
0361   }
0362 protected:
0363   tools::key_code convert_key(WPARAM a_key) {
0364     if(a_key==VK_SHIFT) return tools::sg::key_shift();
0365     return (tools::key_code)a_key;
0366   }
0367 protected:
0368   HWND m_parent;
0369   HWND m_hwnd;
0370   bool m_touch_available;
0371   tools::sg::device_interactor* m_interactor;
0372 };
0373 
0374 }}
0375 
0376 
0377 #endif