// Common, groups WinWrap and WinSystem
// Copyright Alexander Liss
#ifndef __WINSYSTEM_H__
#define __WINSYSTEM_H__
#include <tchar.h>
#include "win0.h"
#include "area.h"
struct AppInstanceData;
struct WindowMessageData;
class Window;
// global structure, has to be created at the start of WinMain
extern AppInstanceData *G_app_instance_data;
// process data
struct AppInstanceData
{
HINSTANCE current,previous;
AppInstanceData(HINSTANCE c,HINSTANCE p):
current(c),previous(p){}
};
// ids
struct WindowTemplateId
{
LPCTSTR name;
HINSTANCE app_instance;
WindowTemplateId(LPCTSTR n,HINSTANCE i):
app_instance(i),name(n){}
WindowTemplateId(LPCTSTR n=0, const AppInstanceData *z=0):
app_instance(0),name(n){if(z) app_instance=z->current;}
};
struct WindowId
{
HINSTANCE app_instance;
HWND window;
WindowId(const AppInstanceData *z=0,HWND w=0):
app_instance(0),window(w){if(z) app_instance=z->current;}
};
// FunctionPaint
class FunctionPaint
{
public:
HDC dc;
PAINTSTRUCT ps;
FunctionPaint(HWND h){ dc=BeginPaint( handle=h, &ps ); }
~FunctionPaint(){ EndPaint( handle, &ps ); }
private:
HWND handle;
};
// Window driver
// a base class for window procedure functions
struct WindowDriver
{
virtual ~WindowDriver(){}
// returns: 0 -> processed, 1 -> pass to next, -1 -> error
virtual int respond(Window& ,WindowMessageData&){return 1;}
// for internal use
static LRESULT CALLBACK generic_procedure(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
static BOOL CALLBACK dialog_procedure(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
};
// window template (window class)
struct WindowTemplateData
{
LPCTSTR menu_name;
UINT style;
HICON icon, small_icon;
HCURSOR cursor;
HBRUSH background;
WNDPROC procedure;
WindowTemplateData():
menu_name(0),
style(CS_VREDRAW | CS_HREDRAW),
icon(0),
small_icon(0),
cursor(0),
background((HBRUSH)( COLOR_BACKGROUND+1 )),
procedure(&WindowDriver::generic_procedure){}
int set_from(const WindowTemplateId& id);
};
/*
struct WindowTemplateDataVariant:public WindowTemplateData
{
WindowTemplateDataVariant()
{
icon=(HICON)LoadImage(0,IDI_APPLICATION, IMAGE_ICON,0,0,LR_DEFAULTSIZE);
small_icon=(HICON)LoadImage(0,IDI_APPLICATION, IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0);
cursor=(HCURSOR)LoadImage(0,IDC_ARROW, IMAGE_CURSOR,0,0,LR_DEFAULTSIZE);
}
~WindowTemplateDataVariant()
{
DestroyIcon(icon);
DestroyIcon(small_icon);
DestroyCursor(cursor);
}
};
*/
class WindowTemplate
{
WindowTemplate(const WindowTemplate&);
WindowTemplate& operator=(const WindowTemplate&);
public:
WindowTemplate():handle(0){}
WindowTemplate(const WindowTemplateData& data,const WindowTemplateId& Id)
{store(data,Id);}
//~WindowTemplate(){}
WindowTemplateId get_id(){return id;}
ATOM get_handle()const{return handle;}
BOOL store(const WindowTemplateData& data,const WindowTemplateId& id);
BOOL remove();
BOOL get_stored(WindowTemplateData& );
private:
WindowTemplateId id;
ATOM handle;
};
// WINDOW
struct WindowData
{
WindowTemplate& window_template;
Area area;
DWORD style,style_ex;
HMENU menu; // menu handle or child identifier
WindowData(WindowTemplate& z):
window_template(z),
style(WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CS_OWNDC),
style_ex(WS_EX_APPWINDOW | WS_EX_OVERLAPPEDWINDOW),
menu(0)
{}
// interprets menu==0 as absence of menu,
// hence, set menu before calling this
BOOL set_client_area(const Area& z);
};
// does not use extra bytes
class Window
{
Window(const Window&);
Window& operator=(const Window&);
public:
Window(HWND h=0):handle(0){if(h) set(h);}
virtual ~Window(){}
int set(HWND h){BOOL z=::IsWindow(h); if(z) handle=h;return !z;}
HWND get_handle()const{return handle;}
int set(const WindowDriver& z)
{ ::SetWindowLong(handle,GWL_USERDATA,(LONG)(&z)); return 0;}
WindowDriver *get_driver()const
{ return (WindowDriver *)::GetWindowLong(handle,GWL_USERDATA);}
// should not call directly - send messages
BOOL destroy();
BOOL minimize()const{return CloseWindow(handle);}
UINT change_base_style(UINT style)const;
HICON change_icon(HICON icon)const;
HICON change_small_icon(HICON small_icon)const;
HCURSOR change_cursor(HCURSOR cursor)const;
HBRUSH change_background(HBRUSH brush)const;
LPCTSTR change_base_menu(LPCTSTR name)const;
DWORD change_style(DWORD style)const;
DWORD change_style_ex(DWORD style)const;
WindowDriver* change_driver(WindowDriver &z);
BOOL store_data( LPCTSTR data_name, HANDLE data);
VOID remove_data( LPCTSTR data_name);
HANDLE get_stored_data(LPCTSTR data_name)const;
BOOL show(int nCmdShow )const{return ::ShowWindow(handle,nCmdShow);}
// send show command into another thread's queue
BOOL show_async(int nCmdShow )const{return ::ShowWindowAsync(handle,nCmdShow);}
// repainting, direct call
BOOL update(){return UpdateWindow(handle);}
BOOL client_area(Area &)const;
BOOL selfsend_destroy_message();
BOOL selfsend_end_thread_message();
protected:
HWND handle;
};
// provides one private Device Context
class GenericWindow:public Window
{
GenericWindow(const GenericWindow&);
GenericWindow& operator=(const GenericWindow&);
public:
GenericWindow(HWND h=0):Window(h){}
// binds window to a calling thread
// passes creation messages to window procedure
// fails if window is already created
int create(LPCTSTR name,
const WindowData&,
const WindowId& parent,
const WindowDriver &driver);
// window's private device content
HDC dc(){return ::GetDC(handle);}
};
class DialogWindow:public Window
{
DialogWindow(const DialogWindow&);
DialogWindow& operator=(const DialogWindow&);
public:
DialogWindow(HWND h=0):Window(h){}
// binds window to a calling thread
// fails if window is already created
int create(
LPCTSTR lpTemplateName, // dialog box template
const WindowId& parent,
const WindowDriver &driver);
};
// WINDOW MESSAGE
struct WindowMessageData
{
UINT message;
WPARAM wparam;
LPARAM lparam;
WindowMessageData(UINT m=0,WPARAM w=0,LPARAM l=0):
message(m),wparam(w),lparam(l){}
};
struct WindowMessageFilter
{
HWND window;
UINT min_id,max_id;
WindowMessageFilter(HWND w=0,UINT mi=0,UINT ma=0):
window(w),min_id(mi),max_id(ma){}
};
// sends to a queue of a thread linked to a window
inline
BOOL send(WindowMessageData& m,HWND window)
{ return ::PostMessage(window,m.message,m.wparam,m.lparam);}
inline
LRESULT send_priority(WindowMessageData& m,HWND window)
{ return ::SendMessage(window,m.message,m.wparam,m.lparam);}
inline
BOOL send(WindowMessageData& m,HWND dialog_window,int item)
{ return ::SendDlgItemMessage(dialog_window,item,m.message,m.wparam,m.lparam);}
inline
BOOL send_to_thread(WindowMessageData& m,DWORD thread_id)
{return ::PostThreadMessage(thread_id,m.message,m.wparam,m.lparam);}
// from a queue of calling thread
inline
BOOL get(LPMSG lpMsg,WindowMessageFilter& filter)
{ return GetMessage(lpMsg,filter.window,filter.min_id,filter.max_id);}
// from a queue of calling thread
inline
BOOL peek(LPMSG lpMsg,WindowMessageFilter& filter,UINT wRemoveMsg=PM_NOREMOVE | PM_NOYIELD)
{ return PeekMessage(lpMsg,filter.window,filter.min_id,filter.max_id,wRemoveMsg);}
// passes to a window procedure
inline
LRESULT dispatch(LPMSG lpMsg)
{return ::DispatchMessage(lpMsg);}
// for some messages, creates a new message and places it in front of queue
inline
BOOL translate(CONST MSG *lpMsg){return ::TranslateMessage(lpMsg);}
// direct calls of a window procedure for some messages
inline
BOOL process_accelerator(LPMSG lpMsg,HWND hWnd,HACCEL hAccTable)
{return (BOOL)::TranslateAccelerator(hWnd,hAccTable,lpMsg);}
// checks if it is a message to a dialog and only then processes it
inline
BOOL check_process_dialog(LPMSG lpMsg,HWND hWnd)
{return ::IsDialogMessage(hWnd,lpMsg);}
// message to a calling thread
inline
VOID send_quit_gui_thread(int exit_code=0){::PostQuitMessage(exit_code);}
int GUI_step( WindowMessageFilter filter,HACCEL accelerator=0 );
// sends destroy message to all top windows of calling thread
VOID winsystem_thread_cleanup();
inline
int message_box(
HWND handle, // window-owner, if zero then has no owner
LPCTSTR lpText,
LPCTSTR lpCaption=_T("Error Info"),
UINT uType=MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND,
WORD wLanguageId=MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) // default language
)
{return ::MessageBoxEx(handle,lpText,lpCaption,uType,wLanguageId);}
VOID last_error_message_box(HWND handle);
#endif