xenocara/xserver/hw/xwin/xlaunch/window/window.cc
2006-11-26 18:13:41 +00:00

285 lines
7.7 KiB
C++

/*
* Copyright (c) 2005 Alexander Gottwald
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in this Software without prior written authorization.
*/
#include "window.h"
#include "util.h"
#include <stdio.h>
#include <stdexcept>
CWindow::CWindowClass CWindow::windowClass("CWINDOWCLASS", DefWindowProc);
CWindow::CWindowClass::CWindowClass(const char *_name, WNDPROC _wndproc) :
wndproc(_wndproc), atom(0), classname(_name)
{
Register();
}
CWindow::CWindowClass::~CWindowClass()
{
UnregisterClass(classname.c_str(), GetModuleHandle(NULL));
}
void CWindow::CWindowClass::Register()
{
WNDCLASSEX wndclass;
memset(&wndclass, 0, sizeof(wndclass));
wndclass.cbSize = sizeof(wndclass);
wndclass.style = 0;
wndclass.lpfnWndProc = wndproc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = GetModuleHandle(NULL);
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = classname.c_str();
wndclass.hIconSm = NULL;
atom = RegisterClassEx(&wndclass);
if (atom == 0)
throw win32_error("RegisterClassEx failed");
}
CWindow::CWindow(const char *_title) : title(_title), hwnd(NULL), parent(NULL), bounds(), owndproc(NULL), showing(FALSE)
{
style = WS_CHILD;
exstyle = 0;
}
HWND CWindow::CreateWindowHandle()
{
HWND ret = CreateWindowEx(
exstyle,
GetClassName(),
title.c_str(),
style,
bounds.left,
bounds.top,
bounds.width,
bounds.height,
parent,
NULL,
GetModuleHandle(NULL),
0
);
if (ret == NULL)
throw win32_error("CreateWindowEx failed");
return ret;
}
void CWindow::Create()
{
if (hwnd != NULL)
return;
hwnd = CreateWindowHandle();
if (hwnd == NULL)
throw win32_error("Could not create window");
// Reset the error code
DWORD err = 0;
SetLastError(err);
// Attach the object reference to the window handle
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
err = GetLastError();
if (err != 0)
throw win32_error("SetWindowLongPtr failed",err);
// Set the window proc
owndproc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WindowProc);
err = GetLastError();
if (err != 0)
throw win32_error("SetWindowLongPtr failed",err);
}
const char *CWindow::GetClassName()
{
return windowClass.GetClassName();
}
LRESULT CALLBACK CWindow::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
MessageDebug::debug(hwnd, uMsg, wParam, lParam, __FUNCTION__);
CWindow* window = (CWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (window != NULL)
return window->Dispatch(hwnd, uMsg, wParam, lParam);
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
LRESULT CWindow::Dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
bounds.width = LOWORD(lParam);
bounds.height = LOWORD(lParam);
break;
case WM_MOVE:
bounds.left = LOWORD(lParam);
bounds.top = LOWORD(lParam);
break;
case WM_DESTROY:
showing = FALSE;
break;
}
if (owndproc)
return CallWindowProc(owndproc, hwnd, uMsg, wParam, lParam);
else
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void CWindow::Show()
{
if (hwnd == NULL)
Create();
ShowWindow(hwnd, SW_SHOWNORMAL);
}
int CWindow::ShowModal()
{
MSG msg;
BOOL bRet;
showing = TRUE;
Show();
while( showing && (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
void CWindow::SetLeft(int left)
{
bounds.left = left;
if (hwnd)
if (!SetWindowPos(hwnd, NULL,
bounds.left, bounds.top,
0, 0,
SWP_NOZORDER | SWP_NOSIZE))
throw win32_error("SetWindowPos failed");
}
void CWindow::SetTop(int top)
{
bounds.top = top;
if (hwnd)
if (!SetWindowPos(hwnd, NULL,
bounds.left, bounds.top,
0, 0,
SWP_NOZORDER | SWP_NOSIZE))
throw win32_error("SetWindowPos failed");
}
void CWindow::SetWidth(int width)
{
bounds.width = width;
if (hwnd)
if (!SetWindowPos(hwnd, NULL,
0, 0,
bounds.width, bounds.height,
SWP_NOZORDER | SWP_NOMOVE))
throw win32_error("SetWindowPos failed");
}
void CWindow::SetHeight(int height)
{
bounds.height = height;
if (hwnd)
if (!SetWindowPos(hwnd, NULL,
0, 0,
bounds.width, bounds.height,
SWP_NOZORDER | SWP_NOMOVE))
throw win32_error("SetWindowPos failed");
}
void CWindow::SetBounds(int left, int top, int width, int height)
{
bounds = CBoundary(left, top, width, height);
if (hwnd)
if (!SetWindowPos(hwnd, NULL,
bounds.left, bounds.top,
bounds.width, bounds.height,
SWP_NOZORDER))
throw win32_error("SetWindowPos failed");
}
void CWindow::SetBounds(const RECT &rect)
{
bounds = rect;
if (hwnd)
if (!SetWindowPos(hwnd, NULL,
bounds.left, bounds.top,
bounds.width, bounds.height,
SWP_NOZORDER))
throw win32_error("SetWindowPos failed");
}
HWND CWindow::GetHandle()
{
if (hwnd == NULL)
Create();
return hwnd;
}
void CWindow::SetParent(CWindow *window)
{
parent = window->GetHandle();
if (hwnd != NULL)
if (::SetParent(hwnd, parent) == NULL)
throw win32_error("SetParent failed");
}
void CWindow::SetStyle(DWORD style)
{
this->style = style;
SetLastError(0);
if (hwnd)
SetWindowLong(hwnd, GWL_STYLE, style);
int err = GetLastError();
if (err != 0)
throw win32_error("SetWindowLong failed", err);
}
void CWindow::SetExStyle(DWORD exstyle)
{
this->exstyle = exstyle;
SetLastError(0);
if (hwnd)
SetWindowLong(hwnd, GWL_EXSTYLE, exstyle);
int err = GetLastError();
if (err != 0)
throw win32_error("SetWindowWLong failed", err);
}