Warning, /include/Geant4/toolx/Windows/window 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_window
0005 #define toolx_Windows_window
0006
0007 #include <windows.h>
0008 #include <windowsx.h>
0009 #include <string>
0010
0011 namespace toolx {
0012 namespace Windows {
0013
0014 class window {
0015 static const std::string& s_class() {
0016 static const std::string s_v("toolx::Windows::window");
0017 return s_v;
0018 }
0019 static void register_class(){
0020 static bool s_done = false; //not const, then not thread safe.
0021 if(!s_done) {
0022 WNDCLASS wc;
0023 wc.style = CS_HREDRAW | CS_VREDRAW;
0024 wc.lpfnWndProc = (WNDPROC)proc;
0025 wc.cbClsExtra = 0;
0026 wc.cbWndExtra = 0;
0027 wc.hInstance = ::GetModuleHandle(NULL);
0028 wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
0029 wc.hCursor = LoadCursor(NULL,IDC_ARROW);
0030 wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
0031 wc.lpszMenuName = (PTSTR)s_class().c_str();
0032 wc.lpszClassName = (PTSTR)s_class().c_str();
0033 ::RegisterClass(&wc);
0034 s_done = true;
0035 }
0036 }
0037 public:
0038 virtual void key_up(){}
0039 virtual void key_down(){}
0040 virtual void key_left(){}
0041 virtual void key_right(){}
0042 virtual void key_escape(){}
0043 virtual void close(){
0044 //if(m_hwnd) ::PostMessage(m_hwnd,WM_QUIT,0,0);
0045 ::PostQuitMessage(0);
0046 }
0047 public:
0048 window(const char* a_title,int a_x,int a_y,unsigned int a_w,unsigned int a_h,unsigned int a_mask = WS_OVERLAPPEDWINDOW)
0049 :m_hwnd(0)
0050 ,m_key_shift(false)
0051 ,m_key_ctrl(false)
0052 ,m_focus_hwnd(0)
0053 {
0054 // WARNING : given a_w,a_h may not be the client area because of various decorations.
0055 // See set_client_area_size() method to enforce a client area size.
0056 register_class();
0057 m_hwnd = ::CreateWindow((PTSTR)s_class().c_str(),
0058 NULL,
0059 a_mask,
0060 a_x,a_y,
0061 a_w,a_h,
0062 NULL,NULL,
0063 ::GetModuleHandle(NULL),
0064 NULL);
0065 if(!m_hwnd) return;
0066 ::SetWindowText(m_hwnd,(PTSTR)a_title);
0067 ::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
0068 }
0069 virtual ~window(){
0070 if(m_hwnd) {
0071 ::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
0072 ::DestroyWindow(m_hwnd);
0073 m_hwnd = 0;
0074 }
0075 }
0076 protected:
0077 window(const window& a_from)
0078 :m_hwnd(0)
0079 ,m_key_shift(a_from.m_key_shift)
0080 ,m_key_ctrl(a_from.m_key_ctrl)
0081 ,m_focus_hwnd(0)
0082 {
0083 /*
0084 if(!a_from.m_hwnd) return;
0085 int w,h;
0086 get_size(a_from.m_hwnd,w,h);
0087 register_class();
0088 m_hwnd = ::CreateWindow(s_class().c_str(),
0089 NULL,
0090 WS_OVERLAPPEDWINDOW,
0091 CW_USEDEFAULT,CW_USEDEFAULT,
0092 w,h,
0093 NULL,NULL,
0094 ::GetModuleHandle(NULL),
0095 NULL);
0096 if(!m_hwnd) return;
0097 ::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
0098 */
0099 }
0100 window& operator=(const window& a_from){
0101 m_key_shift = a_from.m_key_shift;
0102 m_key_ctrl = a_from.m_key_ctrl;
0103 return *this;
0104 }
0105 public:
0106 const window& get_me() const {return *this;}
0107 window& get_me() {return *this;}
0108 bool key_shift() const {return m_key_shift;}
0109 HWND hwnd() const {return m_hwnd;}
0110
0111 void set_client_area_size(unsigned int a_w,unsigned int a_h) {
0112 if(!m_hwnd) return;
0113 RECT wrect;
0114 ::GetWindowRect(m_hwnd,&wrect);
0115 unsigned int ww = wrect.right-wrect.left;
0116 unsigned int wh = wrect.bottom-wrect.top;
0117
0118 RECT carect;
0119 ::GetClientRect(m_hwnd,&carect);
0120 unsigned int cw = carect.right-carect.left;
0121 unsigned int ch = carect.bottom-carect.top;
0122
0123 unsigned int woffset = ww-cw;
0124 unsigned int hoffset = wh-ch;
0125
0126 ::MoveWindow(m_hwnd,wrect.left,wrect.top,a_w+woffset,a_h+hoffset,TRUE);
0127 }
0128 void move(unsigned int a_x,unsigned int a_y) {
0129 if(!m_hwnd) return;
0130 RECT rect;
0131 ::GetWindowRect(m_hwnd,&rect);
0132 unsigned int w = rect.right-rect.left;
0133 unsigned int h = rect.bottom-rect.top;
0134 ::MoveWindow(m_hwnd,a_x,a_y,w,h,TRUE);
0135 }
0136
0137 void set_focus_hwnd(HWND a_hwnd) {m_focus_hwnd = a_hwnd;}
0138 HWND focus_hwnd() const {return m_focus_hwnd;}
0139 protected:
0140 static LRESULT CALLBACK proc(HWND a_hwnd,UINT a_msg,WPARAM a_wparam,LPARAM a_lparam) {
0141 switch (a_msg) {
0142 // Else :
0143 case WM_SIZE:{ // Assume one child window ! FIXME : have a message if not.
0144 int width = LOWORD(a_lparam);
0145 int height = HIWORD(a_lparam);
0146 HWND hwnd = GetFirstChild(a_hwnd);
0147 if(hwnd) {
0148 ::MoveWindow(hwnd,0,0,width,height,TRUE);
0149 }
0150 }return 0;
0151
0152 case WM_SETFOCUS:{
0153 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0154 if(_this) {
0155 HWND hwnd = _this->focus_hwnd();
0156 if(hwnd) ::SetFocus(hwnd);
0157 }
0158 }return 0;
0159
0160 case WM_KEYDOWN:{
0161 switch(a_wparam){
0162 case VK_SHIFT:{
0163 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0164 if(_this) _this->m_key_shift = true;
0165 return 0;
0166 }
0167 case VK_CONTROL:{
0168 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0169 if(_this) _this->m_key_ctrl = true;
0170 return 0;
0171 }
0172 case VK_UP:{
0173 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0174 if(_this) _this->key_up();
0175 return 0;
0176 }
0177 case VK_DOWN:{
0178 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0179 if(_this) _this->key_down();
0180 return 0;
0181 }
0182 case VK_LEFT:{
0183 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0184 if(_this) _this->key_left();
0185 return 0;
0186 }
0187 case VK_RIGHT:{
0188 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0189 if(_this) _this->key_right();
0190 return 0;
0191 }
0192 case VK_ESCAPE:{
0193 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0194 if(_this) _this->key_escape();
0195 return 0;
0196 }
0197 } //end switch(a_wparam)
0198 break;
0199 }
0200 case WM_KEYUP:{
0201 switch(a_wparam){
0202 case VK_SHIFT:{
0203 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0204 if(_this) _this->m_key_shift = false;
0205 return 0;
0206 }
0207 case VK_CONTROL:{
0208 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0209 if(_this) _this->m_key_ctrl = false;
0210 return 0;
0211 }
0212 } //end switch(a_wparam)
0213 break;
0214 }
0215
0216 case WM_CLOSE:{
0217 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0218 if(_this) _this->close();
0219 }break; //NOTE : can't be return 0.
0220 case WM_DESTROY:wm__destroy(a_hwnd);return 0;
0221 }
0222 return (DefWindowProc(a_hwnd,a_msg,a_wparam,a_lparam));
0223 }
0224 static void wm__destroy(HWND a_hwnd) {
0225 window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
0226 if(_this) { //How to be sure that we have a window* ???
0227 if(_this->m_hwnd!=a_hwnd) {
0228 //::printf("WinTk::Component::wm_destroy : HWND mismatch !\n");
0229 }
0230 _this->m_hwnd = 0;
0231 }
0232 ::SetWindowLongPtr(a_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
0233 }
0234 protected:
0235 void get_size(HWND a_hwnd,int& a_w,int& a_h){
0236 RECT rect;
0237 ::GetWindowRect(a_hwnd,&rect);
0238 a_w = rect.right-rect.left;
0239 a_h = rect.bottom-rect.top;
0240 }
0241 protected:
0242 HWND m_hwnd;
0243 bool m_key_shift;
0244 bool m_key_ctrl;
0245 HWND m_focus_hwnd;
0246 };
0247
0248 }}
0249
0250 #endif