Import Geant4 11.1.0.beta source tree
This commit is contained in:
@@ -0,0 +1,418 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Windows_glarea
|
||||
#define toolx_Windows_glarea
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <wingdi.h>
|
||||
|
||||
#include <tools/sg/device_interactor>
|
||||
#include <tools/sg/keys>
|
||||
//#include <tools/log_file>
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#else
|
||||
#define TOOLX_WINDOWS_TOUCH
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
namespace Windows {
|
||||
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
inline bool is_message_touch_event() {
|
||||
// from https://stackoverflow.com/questions/29857587/detect-if-wm-mousemove-is-caused-by-touch-pen.
|
||||
static const LONG_PTR c_SIGNATURE_MASK = 0xFFFFFF00;
|
||||
static const LONG_PTR c_MOUSEEVENTF_FROMTOUCH = 0xFF515700;
|
||||
LONG_PTR extraInfo = ::GetMessageExtraInfo();
|
||||
return ( ( extraInfo & c_SIGNATURE_MASK ) == c_MOUSEEVENTF_FROMTOUCH );
|
||||
}
|
||||
#endif
|
||||
|
||||
class glarea {
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("toolx::Windows::glarea");
|
||||
return s_v;
|
||||
}
|
||||
static void register_class(){
|
||||
static bool s_done = false; //not const, then not thread safe.
|
||||
if(!s_done) {
|
||||
WNDCLASS wc;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = (WNDPROC)proc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = ::GetModuleHandle(NULL);
|
||||
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
|
||||
wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
|
||||
wc.lpszMenuName = s_class().c_str();
|
||||
wc.lpszClassName = s_class().c_str();
|
||||
::RegisterClass(&wc);
|
||||
s_done = true;
|
||||
}
|
||||
}
|
||||
public:
|
||||
virtual void resize(unsigned int,unsigned int){}
|
||||
virtual void paint(unsigned int a_w,unsigned int a_h) {}
|
||||
virtual void close(){}
|
||||
|
||||
virtual void left_button_up(unsigned int a_x,unsigned int a_y) {}
|
||||
virtual void left_button_down(unsigned int a_x,unsigned int a_y) {}
|
||||
virtual void mouse_move(unsigned int a_x,unsigned int a_y,bool) {}
|
||||
public:
|
||||
glarea(HWND a_parent)
|
||||
:m_parent(a_parent)
|
||||
,m_hwnd(0)
|
||||
,m_context(0)
|
||||
,m_HDC(0)
|
||||
,m_touch_available(false)
|
||||
,m_interactor(0)
|
||||
{
|
||||
register_class();
|
||||
// The WS_BORDER is needed. Else probleme of size at startup.
|
||||
RECT rect;
|
||||
::GetClientRect(m_parent,&rect);
|
||||
//printf("debug : glarea : ca : %d %d\n",rect.right-rect.left,rect.bottom-rect.top);
|
||||
//toolx::log_file::get().writef("debug : glarea : ca : %d %d\n",rect.right-rect.left,rect.bottom-rect.top);
|
||||
m_hwnd = ::CreateWindow(s_class().c_str(),
|
||||
NULL,
|
||||
WS_CHILD | WS_VISIBLE,
|
||||
0,0,
|
||||
rect.right-rect.left,
|
||||
rect.bottom-rect.top,
|
||||
m_parent,NULL,
|
||||
GetWindowInstance(m_parent),
|
||||
NULL);
|
||||
if(!m_hwnd) return;
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
|
||||
|
||||
// initialize OpenGL rendering :
|
||||
m_HDC = ::GetDC(m_hwnd);
|
||||
if(m_HDC && SetWindowPixelFormat(m_HDC) ) {
|
||||
m_context = ::wglCreateContext(m_HDC);
|
||||
}
|
||||
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
{BYTE digitizer_status = (BYTE)::GetSystemMetrics(SM_DIGITIZER);
|
||||
if((digitizer_status & (0x80 + 0x40)) == 0) {
|
||||
m_touch_available = false;
|
||||
} else {
|
||||
//BYTE nInputs = (BYTE)::GetSystemMetrics(SM_MAXIMUMTOUCHES);
|
||||
m_touch_available = true;
|
||||
if(!::RegisterTouchWindow(m_hwnd,0)) m_touch_available = false;
|
||||
}}
|
||||
#endif
|
||||
|
||||
}
|
||||
virtual ~glarea(){
|
||||
if(::wglGetCurrentContext()!=NULL) ::wglMakeCurrent(NULL,NULL);
|
||||
if(m_context) {
|
||||
::wglDeleteContext(m_context);
|
||||
m_context = 0;
|
||||
}
|
||||
if(m_HDC && m_hwnd) ::ReleaseDC(m_hwnd,m_HDC);
|
||||
if(m_hwnd) {
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
|
||||
::DestroyWindow(m_hwnd);
|
||||
m_hwnd = 0;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
glarea(const glarea& a_from)
|
||||
:m_parent(a_from.m_parent)
|
||||
,m_hwnd(0)
|
||||
,m_context(0)
|
||||
,m_HDC(0)
|
||||
,m_touch_available(a_from.m_touch_available)
|
||||
,m_interactor(0)
|
||||
{
|
||||
if(!m_parent) return;
|
||||
register_class();
|
||||
RECT rect;
|
||||
::GetClientRect(m_parent,&rect);
|
||||
m_hwnd = ::CreateWindow(s_class().c_str(),
|
||||
NULL,
|
||||
WS_CHILD | WS_VISIBLE,
|
||||
0,0,
|
||||
rect.right-rect.left,
|
||||
rect.bottom-rect.top,
|
||||
m_parent,NULL,
|
||||
GetWindowInstance(m_parent),
|
||||
NULL);
|
||||
if(!m_hwnd) return;
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
|
||||
|
||||
// initialize OpenGL rendering :
|
||||
m_HDC = ::GetDC(m_hwnd);
|
||||
if(m_HDC && SetWindowPixelFormat(m_HDC) ) {
|
||||
m_context = ::wglCreateContext(m_HDC);
|
||||
}
|
||||
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
if(a_from.m_touch_available) {
|
||||
if(!::RegisterTouchWindow(m_hwnd,0)) m_touch_available = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
glarea& operator=(const glarea&){return *this;}
|
||||
public:
|
||||
void set_client_area_size(unsigned int a_w,unsigned int a_h) {
|
||||
RECT rect;
|
||||
::GetClientRect(m_hwnd,&rect);
|
||||
::MoveWindow(m_hwnd,rect.left,rect.top,a_w,a_h,TRUE);
|
||||
}
|
||||
HWND hwnd() const {return m_hwnd;}
|
||||
void post_WM_PAINT() const {
|
||||
::PostMessage(m_hwnd,WM_PAINT,(WPARAM)0,(LPARAM)0);
|
||||
}
|
||||
void send_WM_PAINT() const {
|
||||
::SendMessage(m_hwnd,WM_PAINT,(WPARAM)0,(LPARAM)0);
|
||||
}
|
||||
void wm_paint() {
|
||||
PAINTSTRUCT ps;
|
||||
//HDC hDC =
|
||||
BeginPaint(m_hwnd,&ps);
|
||||
if(m_HDC && m_context) {
|
||||
::wglMakeCurrent(m_HDC,m_context);
|
||||
|
||||
RECT rect;
|
||||
::GetClientRect(m_hwnd,&rect);
|
||||
unsigned int w = rect.right-rect.left;
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
|
||||
//printf("debug : glarea : paint : %d %d\n",w,h);
|
||||
//toolx::log_file::get().writef("debug : glarea : paint : %d %d\n",w,h);
|
||||
|
||||
paint(w,h);
|
||||
|
||||
::SwapBuffers(m_HDC);
|
||||
::wglMakeCurrent(m_HDC,0);
|
||||
}
|
||||
EndPaint(m_hwnd,&ps);
|
||||
}
|
||||
public:
|
||||
void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} //we do not have ownership.
|
||||
protected:
|
||||
bool is_touch_event() {
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
if(!m_touch_available) return false;
|
||||
return is_message_touch_event();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
static LRESULT CALLBACK proc(HWND a_hwnd,UINT a_msg,WPARAM a_wparam,LPARAM a_lparam) {
|
||||
switch (a_msg) {
|
||||
case WM_SIZE:{
|
||||
int width = LOWORD(a_lparam);
|
||||
int height = HIWORD(a_lparam);
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
_this->resize(width,height);
|
||||
} else {
|
||||
// CreateWindow send a WM_SIZE but GWLP_USERDATA not yet set.
|
||||
}
|
||||
}return 0;
|
||||
case WM_PAINT:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->wm_paint();
|
||||
}return 0;
|
||||
|
||||
case WM_KEYDOWN:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::key_down_event event(_this->convert(a_wparam));
|
||||
_this->m_interactor->key_press(event);
|
||||
}
|
||||
}
|
||||
} return 0;
|
||||
case WM_KEYUP:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::key_up_event event(_this->convert(a_wparam));
|
||||
_this->m_interactor->key_release(event);
|
||||
}
|
||||
}
|
||||
} return 0;
|
||||
|
||||
case WM_LBUTTONDOWN:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::mouse_down_event event(LOWORD(a_lparam),HIWORD(a_lparam));
|
||||
_this->m_interactor->mouse_press(event);
|
||||
} else {
|
||||
RECT rect;
|
||||
::GetClientRect(a_hwnd,&rect);
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
if(!_this->is_touch_event()) _this->left_button_down(LOWORD(a_lparam),h-HIWORD(a_lparam));
|
||||
}
|
||||
}
|
||||
}return 0;
|
||||
case WM_LBUTTONUP:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::mouse_up_event event(LOWORD(a_lparam),HIWORD(a_lparam));
|
||||
_this->m_interactor->mouse_release(event);
|
||||
} else {
|
||||
RECT rect;
|
||||
::GetClientRect(a_hwnd,&rect);
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
if(!_this->is_touch_event()) _this->left_button_up(LOWORD(a_lparam),h-HIWORD(a_lparam));
|
||||
}
|
||||
}
|
||||
} return 0;
|
||||
case WM_MOUSEMOVE:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::mouse_move_event event(LOWORD(a_lparam),HIWORD(a_lparam),0,0,false);
|
||||
_this->m_interactor->mouse_move(event);
|
||||
} else {
|
||||
WPARAM state = a_wparam;
|
||||
bool ldown = ((state & MK_LBUTTON)==MK_LBUTTON)?true:false;
|
||||
RECT rect;
|
||||
::GetClientRect(a_hwnd,&rect);
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
if(!_this->is_touch_event()) _this->mouse_move(LOWORD(a_lparam),h-HIWORD(a_lparam),ldown);
|
||||
}
|
||||
}
|
||||
|
||||
}return 0;
|
||||
|
||||
case WM_MOUSEWHEEL:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::wheel_rotate_event event(GET_WHEEL_DELTA_WPARAM(a_wparam));
|
||||
_this->m_interactor->wheel_rotate(event);
|
||||
}
|
||||
}
|
||||
} return 0;
|
||||
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
case WM_TOUCH:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this && _this->m_touch_available) {
|
||||
RECT rect;
|
||||
//::GetWindowRect(hwnd,&rect); ???
|
||||
::GetClientRect(a_hwnd,&rect);
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
|
||||
unsigned int num_inputs = (int)a_wparam;
|
||||
//::printf("debug : WM_TOUCH : 001 : %d\n",num_inputs);
|
||||
TOUCHINPUT* ti = new TOUCHINPUT[num_inputs];
|
||||
POINT p;
|
||||
if(::GetTouchInputInfo((HTOUCHINPUT)a_lparam,num_inputs,ti,sizeof(TOUCHINPUT))) {
|
||||
for(unsigned int i=0;i<num_inputs; ++i) {
|
||||
p.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
|
||||
p.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
|
||||
if(!::ScreenToClient(a_hwnd,&p)) {}
|
||||
if(ti[i].dwFlags & TOUCHEVENTF_DOWN) {
|
||||
//::printf("debug : TOUCHEVENTF_DOWN %lu %lu\n",p.x,p.y);
|
||||
_this->left_button_down(p.x,h-p.y);
|
||||
} else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
|
||||
//::printf("debug : TOUCHEVENTF_UP %lu %lu\n",p.x,p.y);
|
||||
_this->left_button_up(p.x,h-p.y);
|
||||
} else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
|
||||
bool ldown = true; //we assume that a TOUCHEVENT_DOWN had been done.
|
||||
//::printf("debug : TOUCHEVENTF_MOVE %lu %lu\n",p.x,p.y);
|
||||
_this->mouse_move(p.x,h-p.y,ldown);
|
||||
}
|
||||
}
|
||||
}
|
||||
::CloseTouchInputHandle((HTOUCHINPUT)a_lparam);
|
||||
delete [] ti;
|
||||
}
|
||||
}return 0;
|
||||
#endif //TOOLX_WINDOWS_TOUCH
|
||||
case WM_DESTROY:wm__destroy(a_hwnd);return 0;
|
||||
}
|
||||
return (DefWindowProc(a_hwnd,a_msg,a_wparam,a_lparam));
|
||||
}
|
||||
static bool SetWindowPixelFormat(HDC a_HDC){
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags =
|
||||
PFD_DRAW_TO_WINDOW |
|
||||
PFD_SUPPORT_OPENGL |
|
||||
PFD_DOUBLEBUFFER |
|
||||
PFD_STEREO_DONTCARE;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cRedBits = 8;
|
||||
pfd.cRedShift = 16;
|
||||
pfd.cGreenBits = 8;
|
||||
pfd.cGreenShift = 8;
|
||||
pfd.cBlueBits = 8;
|
||||
pfd.cBlueShift = 0;
|
||||
pfd.cAlphaBits = 0;
|
||||
pfd.cAlphaShift = 0;
|
||||
pfd.cAccumBits = 64;
|
||||
pfd.cAccumRedBits = 16;
|
||||
pfd.cAccumGreenBits = 16;
|
||||
pfd.cAccumBlueBits = 16;
|
||||
pfd.cAccumAlphaBits = 0;
|
||||
pfd.cDepthBits = 32;
|
||||
pfd.cStencilBits = 8;
|
||||
pfd.cAuxBuffers = 0;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
pfd.bReserved = 0;
|
||||
pfd.dwLayerMask = 0;
|
||||
pfd.dwVisibleMask = 0;
|
||||
pfd.dwDamageMask = 0;
|
||||
|
||||
int pixelIndex = ::ChoosePixelFormat(a_HDC,&pfd);
|
||||
if (pixelIndex==0) {
|
||||
// Let's choose a default index.
|
||||
pixelIndex = 1;
|
||||
if (::DescribePixelFormat(a_HDC,
|
||||
pixelIndex,
|
||||
sizeof(PIXELFORMATDESCRIPTOR),
|
||||
&pfd)==0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (::SetPixelFormat(a_HDC,pixelIndex,&pfd)==FALSE) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
static void wm__destroy(HWND a_hwnd) {
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) { //How to be sure that we have a glarea* ???
|
||||
_this->close();
|
||||
if(_this->m_hwnd!=a_hwnd) {
|
||||
//::printf("WinTk::Component::wm_destroy : HWND mismatch !\n");
|
||||
}
|
||||
_this->m_hwnd = 0;
|
||||
}
|
||||
::SetWindowLongPtr(a_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
|
||||
}
|
||||
protected:
|
||||
tools::key_code convert(WPARAM a_key) {
|
||||
if(a_key==VK_SHIFT) return tools::sg::key_shift();
|
||||
return (tools::key_code)a_key;
|
||||
}
|
||||
protected:
|
||||
HWND m_parent;
|
||||
HWND m_hwnd;
|
||||
HGLRC m_context;
|
||||
HDC m_HDC;
|
||||
bool m_touch_available;
|
||||
tools::sg::device_interactor* m_interactor;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Windows_session
|
||||
#define toolx_Windows_session
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace toolx {
|
||||
namespace Windows {
|
||||
|
||||
class session {
|
||||
public:
|
||||
session(std::ostream& a_out):m_out(a_out){}
|
||||
virtual ~session() {}
|
||||
protected:
|
||||
session(const session& a_from):m_out(a_from.m_out){}
|
||||
session& operator=(const session&){return *this;}
|
||||
public:
|
||||
std::ostream& out() const {return m_out;}
|
||||
|
||||
bool is_valid() const {return true;}
|
||||
|
||||
bool steer() {
|
||||
while(true) {
|
||||
MSG event;
|
||||
BOOL status = ::GetMessage(&event,NULL,0,0);
|
||||
if(status == -1) { // This may happen (dixit Microsoft doc).
|
||||
break;
|
||||
} else if(status == 0) { //WM_QUIT
|
||||
break;
|
||||
} else {
|
||||
::TranslateMessage(&event);
|
||||
::DispatchMessage (&event);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sync() {
|
||||
MSG event;
|
||||
while(::PeekMessage(&event,NULL,0,0,PM_REMOVE)) {
|
||||
if(event.message==WM_QUIT) return false;
|
||||
::TranslateMessage(&event);
|
||||
::DispatchMessage(&event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void show_window(HWND a_hwnd){
|
||||
::SetForegroundWindow(a_hwnd);
|
||||
::ShowWindow(a_hwnd,SW_SHOWDEFAULT);
|
||||
::UpdateWindow(a_hwnd);
|
||||
::DrawMenuBar(a_hwnd);
|
||||
}
|
||||
|
||||
void set_size(HWND a_hwnd,unsigned int a_width,unsigned int a_height) {
|
||||
::MoveWindow(a_hwnd,0,0,a_width,a_height,TRUE);
|
||||
}
|
||||
|
||||
//void post(HWND a_hwnd,LPARAM a_msg){
|
||||
// ::PostMessage(a_hwnd,WM_USER,(WPARAM)0,a_msg);
|
||||
//}
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Windows_sg_viewer
|
||||
#define toolx_Windows_sg_viewer
|
||||
|
||||
#include "session"
|
||||
#include "window"
|
||||
#include "glarea"
|
||||
|
||||
#include "../sg/GL_viewer"
|
||||
|
||||
// disable the warning about the usage of "this" in the constructor.
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
namespace toolx {
|
||||
namespace Windows {
|
||||
|
||||
class sg_viewer : public window, public sg::GL_viewer {
|
||||
typedef window parent_window;
|
||||
typedef sg::GL_viewer parent_viewer;
|
||||
public:
|
||||
virtual void close() {}
|
||||
public:
|
||||
sg_viewer(session& a_session,
|
||||
int a_x = 0,int a_y = 0,
|
||||
unsigned int a_width = 500,unsigned int a_height = 500,
|
||||
const std::string& a_title = "")
|
||||
:parent_window(a_title.c_str(),a_x,a_y,a_width,a_height)
|
||||
,parent_viewer(a_session.out(),a_width,a_height)
|
||||
,m_session(a_session)
|
||||
,m_glarea(m_hwnd,*this)
|
||||
{
|
||||
parent_window::set_focus_hwnd(m_glarea.hwnd());
|
||||
}
|
||||
virtual ~sg_viewer() {}
|
||||
protected:
|
||||
sg_viewer(const sg_viewer& a_from)
|
||||
:parent_window(a_from)
|
||||
,parent_viewer(a_from)
|
||||
,m_session(a_from.m_session)
|
||||
,m_glarea(a_from.m_glarea)
|
||||
{}
|
||||
sg_viewer& operator=(const sg_viewer& a_from){
|
||||
parent_window::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool has_window() const {return m_hwnd?true:false;} //for SWIG
|
||||
|
||||
HWND window() const {return m_hwnd;}
|
||||
|
||||
bool show() {
|
||||
if(!m_hwnd) return false;
|
||||
m_session.show_window(m_hwnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void win_render() {m_glarea.wm_paint();}
|
||||
|
||||
|
||||
public:
|
||||
void set_device_interactor(tools::sg::device_interactor* a_interactor) { //we do not have ownership.
|
||||
m_glarea.set_device_interactor(a_interactor);
|
||||
}
|
||||
protected:
|
||||
class _glarea : public glarea {
|
||||
public:
|
||||
virtual void paint(unsigned int a_w,unsigned int a_h) {
|
||||
m_viewer.set_size(a_w,a_h);
|
||||
m_viewer.render();
|
||||
}
|
||||
public:
|
||||
_glarea(HWND a_parent,parent_viewer& a_viewer)
|
||||
:glarea(a_parent)
|
||||
,m_viewer(a_viewer)
|
||||
{}
|
||||
protected:
|
||||
parent_viewer& m_viewer;
|
||||
};
|
||||
|
||||
protected:
|
||||
session& m_session;
|
||||
_glarea m_glarea;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,250 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Windows_window
|
||||
#define toolx_Windows_window
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <string>
|
||||
|
||||
namespace toolx {
|
||||
namespace Windows {
|
||||
|
||||
class window {
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("toolx::Windows::window");
|
||||
return s_v;
|
||||
}
|
||||
static void register_class(){
|
||||
static bool s_done = false; //not const, then not thread safe.
|
||||
if(!s_done) {
|
||||
WNDCLASS wc;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = (WNDPROC)proc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = ::GetModuleHandle(NULL);
|
||||
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
|
||||
wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
|
||||
wc.lpszMenuName = s_class().c_str();
|
||||
wc.lpszClassName = s_class().c_str();
|
||||
::RegisterClass(&wc);
|
||||
s_done = true;
|
||||
}
|
||||
}
|
||||
public:
|
||||
virtual void key_up(){}
|
||||
virtual void key_down(){}
|
||||
virtual void key_left(){}
|
||||
virtual void key_right(){}
|
||||
virtual void key_escape(){}
|
||||
virtual void close(){
|
||||
//if(m_hwnd) ::PostMessage(m_hwnd,WM_QUIT,0,0);
|
||||
::PostQuitMessage(0);
|
||||
}
|
||||
public:
|
||||
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)
|
||||
:m_hwnd(0)
|
||||
,m_key_shift(false)
|
||||
,m_key_ctrl(false)
|
||||
,m_focus_hwnd(0)
|
||||
{
|
||||
// WARNING : given a_w,a_h may not be the client area because of various decorations.
|
||||
// See set_client_area_size() method to enforce a client area size.
|
||||
register_class();
|
||||
m_hwnd = ::CreateWindow(s_class().c_str(),
|
||||
NULL,
|
||||
a_mask,
|
||||
a_x,a_y,
|
||||
a_w,a_h,
|
||||
NULL,NULL,
|
||||
::GetModuleHandle(NULL),
|
||||
NULL);
|
||||
if(!m_hwnd) return;
|
||||
::SetWindowText(m_hwnd,a_title);
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
|
||||
}
|
||||
virtual ~window(){
|
||||
if(m_hwnd) {
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
|
||||
::DestroyWindow(m_hwnd);
|
||||
m_hwnd = 0;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
window(const window& a_from)
|
||||
:m_hwnd(0)
|
||||
,m_key_shift(a_from.m_key_shift)
|
||||
,m_key_ctrl(a_from.m_key_ctrl)
|
||||
,m_focus_hwnd(0)
|
||||
{
|
||||
/*
|
||||
if(!a_from.m_hwnd) return;
|
||||
int w,h;
|
||||
get_size(a_from.m_hwnd,w,h);
|
||||
register_class();
|
||||
m_hwnd = ::CreateWindow(s_class().c_str(),
|
||||
NULL,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,CW_USEDEFAULT,
|
||||
w,h,
|
||||
NULL,NULL,
|
||||
::GetModuleHandle(NULL),
|
||||
NULL);
|
||||
if(!m_hwnd) return;
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
|
||||
*/
|
||||
}
|
||||
window& operator=(const window& a_from){
|
||||
m_key_shift = a_from.m_key_shift;
|
||||
m_key_ctrl = a_from.m_key_ctrl;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
const window& get_me() const {return *this;}
|
||||
window& get_me() {return *this;}
|
||||
bool key_shift() const {return m_key_shift;}
|
||||
HWND hwnd() const {return m_hwnd;}
|
||||
|
||||
void set_client_area_size(unsigned int a_w,unsigned int a_h) {
|
||||
if(!m_hwnd) return;
|
||||
RECT wrect;
|
||||
::GetWindowRect(m_hwnd,&wrect);
|
||||
unsigned int ww = wrect.right-wrect.left;
|
||||
unsigned int wh = wrect.bottom-wrect.top;
|
||||
|
||||
RECT carect;
|
||||
::GetClientRect(m_hwnd,&carect);
|
||||
unsigned int cw = carect.right-carect.left;
|
||||
unsigned int ch = carect.bottom-carect.top;
|
||||
|
||||
unsigned int woffset = ww-cw;
|
||||
unsigned int hoffset = wh-ch;
|
||||
|
||||
::MoveWindow(m_hwnd,wrect.left,wrect.top,a_w+woffset,a_h+hoffset,TRUE);
|
||||
}
|
||||
void move(unsigned int a_x,unsigned int a_y) {
|
||||
if(!m_hwnd) return;
|
||||
RECT rect;
|
||||
::GetWindowRect(m_hwnd,&rect);
|
||||
unsigned int w = rect.right-rect.left;
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
::MoveWindow(m_hwnd,a_x,a_y,w,h,TRUE);
|
||||
}
|
||||
|
||||
void set_focus_hwnd(HWND a_hwnd) {m_focus_hwnd = a_hwnd;}
|
||||
HWND focus_hwnd() const {return m_focus_hwnd;}
|
||||
protected:
|
||||
static LRESULT CALLBACK proc(HWND a_hwnd,UINT a_msg,WPARAM a_wparam,LPARAM a_lparam) {
|
||||
switch (a_msg) {
|
||||
// Else :
|
||||
case WM_SIZE:{ // Assume one child window ! FIXME : have a message if not.
|
||||
int width = LOWORD(a_lparam);
|
||||
int height = HIWORD(a_lparam);
|
||||
HWND hwnd = GetFirstChild(a_hwnd);
|
||||
if(hwnd) {
|
||||
::MoveWindow(hwnd,0,0,width,height,TRUE);
|
||||
}
|
||||
}return 0;
|
||||
|
||||
case WM_SETFOCUS:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
HWND hwnd = _this->focus_hwnd();
|
||||
if(hwnd) ::SetFocus(hwnd);
|
||||
}
|
||||
}return 0;
|
||||
|
||||
case WM_KEYDOWN:{
|
||||
switch(a_wparam){
|
||||
case VK_SHIFT:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->m_key_shift = true;
|
||||
return 0;
|
||||
}
|
||||
case VK_CONTROL:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->m_key_ctrl = true;
|
||||
return 0;
|
||||
}
|
||||
case VK_UP:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_up();
|
||||
return 0;
|
||||
}
|
||||
case VK_DOWN:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_down();
|
||||
return 0;
|
||||
}
|
||||
case VK_LEFT:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_left();
|
||||
return 0;
|
||||
}
|
||||
case VK_RIGHT:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_right();
|
||||
return 0;
|
||||
}
|
||||
case VK_ESCAPE:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_escape();
|
||||
return 0;
|
||||
}
|
||||
} //end switch(a_wparam)
|
||||
break;
|
||||
}
|
||||
case WM_KEYUP:{
|
||||
switch(a_wparam){
|
||||
case VK_SHIFT:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->m_key_shift = false;
|
||||
return 0;
|
||||
}
|
||||
case VK_CONTROL:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->m_key_ctrl = false;
|
||||
return 0;
|
||||
}
|
||||
} //end switch(a_wparam)
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CLOSE:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->close();
|
||||
}break; //NOTE : can't be return 0.
|
||||
case WM_DESTROY:wm__destroy(a_hwnd);return 0;
|
||||
}
|
||||
return (DefWindowProc(a_hwnd,a_msg,a_wparam,a_lparam));
|
||||
}
|
||||
static void wm__destroy(HWND a_hwnd) {
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) { //How to be sure that we have a window* ???
|
||||
if(_this->m_hwnd!=a_hwnd) {
|
||||
//::printf("WinTk::Component::wm_destroy : HWND mismatch !\n");
|
||||
}
|
||||
_this->m_hwnd = 0;
|
||||
}
|
||||
::SetWindowLongPtr(a_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
|
||||
}
|
||||
protected:
|
||||
void get_size(HWND a_hwnd,int& a_w,int& a_h){
|
||||
RECT rect;
|
||||
::GetWindowRect(a_hwnd,&rect);
|
||||
a_w = rect.right-rect.left;
|
||||
a_h = rect.bottom-rect.top;
|
||||
}
|
||||
protected:
|
||||
HWND m_hwnd;
|
||||
bool m_key_shift;
|
||||
bool m_key_ctrl;
|
||||
HWND m_focus_hwnd;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user