233 lines
6.7 KiB
Plaintext
233 lines
6.7 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 = (PTSTR)s_class().c_str();
|
|
wc.lpszClassName = (PTSTR)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(){
|
|
::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((PTSTR)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,(PTSTR)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)
|
|
{
|
|
}
|
|
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) {
|
|
}
|
|
_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
|