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