251 lines
7.3 KiB
Plaintext
251 lines
7.3 KiB
Plaintext
// 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
|