|
Source listing: echo $file; ?>. Return to
the main page
/* -*- C++ -*-
*******************************************************************
*
*
* wndcore.cpp - core window class implementations
*
*
*******************************************************************
*
* General purpose window classes for Win32
*
*******************************************************************
*
* Created 2001-02-20 by Jim Mason <jmason@sirius.com>
*
* Copyright (C) 2001 Jim Mason.
*
*******************************************************************
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*******************************************************************
*/
#include "stdafx.h"
#include "wndcore.h"
// External functions
#include "shisen.h"
HINSTANCE App::GetHInstance(); // returns the HINSTANCE of the application
HWND App::GetMainHWnd(); // returns the HWND of the main application window
/////////////////////////////////////////////////////////////////////////////
// Window superclass
Window::Window() {
m_hWnd = NULL;
m_oldWndProc = NULL;
}
Window::~Window() {
if(m_hWnd && m_oldWndProc) {
// The window is not gone, but our C++ class instance is
// being deleted; it is likely that someone has incorrectly
// coded to explicitly delete the C++ instance, rather than
// destroying the window. We'll assert in debug mode so the
// programmer will know:
ASSERT(FALSE);
// For all C++ objects which are allocated on the heap and
// require explicit deletion, you should override PostNcDestroy
// in your derived class and do a "delete this" there; then
// when you do a DestroyWindow on the window, both the window
// and the C++ class instance will be destroyed.
// If we did a DestroyWindow at this point, the subclass's
// OnDestroy, PostNcDestroy, etc., would never be run, as the
// derived class(es) have already been destructed, and the C++
// vtbl is no longer setup correctly.
//
// We will just unhook our wndproc from the window.
SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_oldWndProc);
SetWindowLong(m_hWnd, GWL_USERDATA, 0L);
}
}
BOOL Window::Create(DWORD dwStyleEx, LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
DWORD dwStyle, const RECT& rect, HWND hParentWnd, UINT nID) {
CREATESTRUCT cs;
cs.dwExStyle = dwStyleEx;
cs.lpszClass = lpszClassName;
cs.lpszName = lpszWindowName;
cs.style = dwStyle;
cs.x = rect.left;
cs.y = rect.top;
cs.cx = rect.right - rect.left;
cs.cy = rect.bottom - rect.top;
cs.hwndParent = hParentWnd;
cs.hMenu = (HMENU)nID;
if(PreCreateWindow(cs)) {
m_hWnd = CreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style,
cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu,
App::GetHInstance(), this);
if(m_hWnd && (WNDPROC)GetWindowLong(m_hWnd, GWL_WNDPROC) != StaticWndProc) {
// If our window proc is not registered as the window proc, do so now.
SubclassWindow(m_hWnd);
// We have missed the creation messages; at least run OnCreate.
if(OnCreate(&cs) == -1) {
DestroyWindow(m_hWnd);
return FALSE;
}
}
}
return m_hWnd != NULL;
}
void Window::SubclassWindow(HWND hWnd) {
if(m_oldWndProc == NULL) {
// Let PreSubclassWindow have a go first
PreSubclassWindow();
// Hook in our window proc
m_hWnd = hWnd;
SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);
m_oldWndProc = (WNDPROC)GetWindowLong(m_hWnd, GWL_WNDPROC);
SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)StaticWndProc);
}
}
void Window::SubclassDlgItem(UINT nID, Window* pParent) {
SubclassWindow(pParent->GetDlgItem(nID));
}
ATOM Window::RegisterClass(WNDCLASS* pwc) {
// Setup our window proc as the class wndproc
pwc->lpfnWndProc = (WNDPROC)StaticWndProc;
return ::RegisterClass(pwc);
}
ATOM Window::RegisterClassEx(WNDCLASSEX* pwcex) {
// Setup our window proc as the class wndproc
pwcex->lpfnWndProc = (WNDPROC)StaticWndProc;
return ::RegisterClassEx(pwcex);
}
LRESULT Window::StaticWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) {
Window* pThis;
switch(nMsg) {
case WM_CREATE:
pThis = (Window*)((LPCREATESTRUCT)lParam)->lpCreateParams;
ASSERT(pThis);
pThis->m_hWnd = hWnd;
SetWindowLong(hWnd, GWL_USERDATA, (long)pThis);
break;
case WM_INITDIALOG:
pThis = (Window*)lParam;
ASSERT(pThis);
pThis->m_hWnd = hWnd;
SetWindowLong(hWnd, GWL_USERDATA, lParam);
break;
case WM_NCDESTROY:
pThis = (Window*)GetWindowLong(hWnd, GWL_USERDATA);
ASSERT(pThis);
if(pThis->m_oldWndProc) {
// Unhook our window proc...
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pThis->m_oldWndProc);
// ...call the old wndproc...
(*pThis->m_oldWndProc)(hWnd, nMsg, wParam, lParam);
pThis->m_oldWndProc = NULL;
}
// ...then finally call PostNcDestroy
pThis->m_hWnd = NULL;
pThis->PostNcDestroy();
return 0L;
default:
pThis = (Window*)GetWindowLong(hWnd, GWL_USERDATA);
break;
}
// Dispatch to the instance WndProc
return pThis?pThis->WndProc(nMsg, wParam, lParam):
DefWindowProc(hWnd, nMsg, wParam, lParam);
}
LRESULT Window::WndProc(UINT nMsg, WPARAM wParam, LPARAM lParam) {
// Called to handle a message
//
// The default implementation handles OnCreate, OnDestroy,
// and OnCommand; it passes all other messages onto the
// default handler (either the old window proc or DefWindowProc).
//
// You may override in your derived class to handle additional
// messages.
switch (nMsg) {
case WM_CREATE:
return OnCreate((LPCREATESTRUCT)lParam);
case WM_DESTROY:
OnDestroy();
return 0L;
case WM_COMMAND:
return OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
}
// Default behaviour is to hand off to the original window proc
return m_oldWndProc?(*m_oldWndProc)(m_hWnd, nMsg, wParam, lParam):
DefWindowProc(m_hWnd, nMsg, wParam, lParam);
}
BOOL Window::PreCreateWindow(CREATESTRUCT &cs) {
// Called just prior to creation of a new window
//
// The default implementation does nothing.
//
// You can override this in your derived class to change
// window styles, register new window classes, etc.
//
// Return FALSE to abort window creation.
return TRUE;
}
void Window::PreSubclassWindow() {
// Called just prior to subclassing an existing window
//
// The default implementation does nothing.
//
// You can override in your derived class to register new
// window classes, etc.
}
void Window::PostNcDestroy() {
// This is called after WM_NCDESTROY has been handled. The
// window should now be considered destroyed; this is the last
// message the window will ever see.
//
// The default implementation does nothing.
//
// You can override in your derived class to do final cleanup, such
// as doing "delete this" on objects that reqire explicit deletion.
}
int Window::OnCreate(LPCREATESTRUCT lpCreateStruct) {
// This is called just after window creation.
//
// Note that for Dialogs, this method is never called; see
// Dialog::OnInitDialog.
//
// The default implementation calls the DefWindowProc.
//
// Return 0 if successful; to abort window creation, return -1.
return DefWindowProc(m_hWnd, WM_CREATE, 0, (LPARAM)lpCreateStruct);
}
void Window::OnDestroy() {
// This is called just as the window is being destroyed.
//
// The default implementation calls the DefWindowProc.
//
// You can override in your derived class to release any resources
// or do cleanup as needed.
DefWindowProc(m_hWnd, WM_DESTROY, 0, 0L);
}
BOOL Window::OnCommand(UINT nID, UINT nEvent, HWND hSource) {
// This is called upon receipt of a WM_COMMAND message.
//
// You can override in your derived class to handle any commands
// your window expects to receive.
//
// Return TRUE if you handle the message; FALSE otherwise.
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Dialog superclass
Dialog::Dialog(LPCTSTR szTemplateName, Window* pParent) {
m_szTemplateName = szTemplateName;
m_pParent = pParent;
}
Dialog::Dialog(UINT nTempateID, Window* pParent) {
m_szTemplateName = MAKEINTRESOURCE(nTempateID);
m_pParent = pParent;
}
int Dialog::DoModal() {
return DialogBoxParam(App::GetHInstance(), m_szTemplateName,
m_pParent?m_pParent->GetHWnd():App::GetMainHWnd(),
(DLGPROC)StaticWndProc, (LPARAM)this);
}
LRESULT Dialog::WndProc(UINT nMsg, WPARAM wParam, LPARAM lParam) {
// Called to handle a message
//
// The default implementation handles OnInitDialog and OnCommand; it
// lets the dialog manager handle all other messages.
//
// You may override in your derived class to handle additional
// messages.
switch (nMsg) {
case WM_INITDIALOG:
return OnInitDialog();
case WM_COMMAND:
return OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
}
// Unlike Window::WndProc, we don't want to call DefWindowProc here,
// as the dialog manager will handle un-handled messages for us.
return 0L;
}
BOOL Dialog::OnInitDialog() {
// This is called just after dialog creation. The dialog resources
// have been created, but are not yet visible.
//
// The default implementation centres the dialog on the application.
//
// You can override in your derived class to initialize dialog
// controls.
//
// Return TRUE unless you explicitly set the focus to a control.
// Centre dialog in frame
RECT rcDlg, rcFrame;
GetWindowRect(&rcDlg);
if(m_pParent)
m_pParent->GetWindowRect(&rcFrame);
else
::GetWindowRect(App::GetMainHWnd(), &rcFrame);
OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
OffsetRect(&rcDlg, (rcFrame.right - rcFrame.left - rcDlg.right) / 2,
(rcFrame.bottom - rcFrame.top - rcDlg.bottom) / 3);
OffsetRect(&rcDlg, rcFrame.left, rcFrame.top);
MoveWindow(rcDlg, FALSE);
// Return TRUE, as we have not set focus.
return TRUE;
}
BOOL Dialog::OnCommand(UINT nID, UINT nEvent, HWND hSource) {
// This is called upon receipt of a WM_COMMAND message.
//
// You can override in your derived class to handle any commands
// your dialog expects to receive.
//
// Return TRUE if you handle the message; FALSE otherwise.
// Handle OK and CANCEL button actions
if (nID == IDOK || nID == IDCANCEL) {
EndDialog(m_hWnd, nID);
return TRUE;
}
return Window::OnCommand(nID, nEvent, hSource);
}
<< Back to Shisen-Sho
|
|