#ifndef __UIBASE_H__
#define __UIBASE_H__
#pragma once
namespace DuiLib {
/
//
#define UI_WNDSTYLE_CONTAINER (0)
#define UI_WNDSTYLE_FRAME (WS_VISIBLE | WS_OVERLAPPEDWINDOW)
#define UI_WNDSTYLE_CHILD (WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
#define UI_WNDSTYLE_DIALOG (WS_VISIBLE | WS_POPUPWINDOW | WS_CAPTION | WS_DLGFRAME | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
#define UI_WNDSTYLE_EX_FRAME (WS_EX_WINDOWEDGE)
#define UI_WNDSTYLE_EX_DIALOG (WS_EX_TOOLWINDOW | WS_EX_DLGMODALFRAME)
#define UI_CLASSSTYLE_CONTAINER (0)
#define UI_CLASSSTYLE_FRAME (CS_VREDRAW | CS_HREDRAW)
#define UI_CLASSSTYLE_CHILD (CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_SAVEBITS)
#define UI_CLASSSTYLE_DIALOG (CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_SAVEBITS)
/
//
#ifndef ASSERT
#define ASSERT(expr) _ASSERTE(expr)
#endif
#ifdef _DEBUG
#ifndef DUITRACE
#define DUITRACE DUI__Trace
#endif
#define DUITRACEMSG DUI__TraceMsg
#else
#ifndef DUITRACE
#define DUITRACE
#endif
#define DUITRACEMSG _T("")
#endif
void UILIB_API DUI__Trace(LPCTSTR pstrFormat, ...);
LPCTSTR UILIB_API DUI__TraceMsg(UINT uMsg);
/
//
class UILIB_API CNotifyPump
{
public:
bool AddVirtualWnd(CDuiString strName,CNotifyPump* pObject);
bool RemoveVirtualWnd(CDuiString strName);
void NotifyPump(TNotifyUI& msg);
bool LoopDispatch(TNotifyUI& msg);
DUI_DECLARE_MESSAGE_MAP()
private:
CStdStringPtrMap m_VirtualWndMap;
};
class UILIB_API CWindowWnd
{
public:
CWindowWnd();
HWND GetHWND() const;
operator HWND() const;
bool RegisterWindowClass();
bool RegisterSuperclass();
HWND Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, const RECT rc, HMENU hMenu = NULL);
HWND Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int cx = CW_USEDEFAULT, int cy = CW_USEDEFAULT, HMENU hMenu = NULL);
HWND CreateDuiWindow(HWND hwndParent, LPCTSTR pstrWindowName,DWORD dwStyle =0, DWORD dwExStyle =0);
HWND Subclass(HWND hWnd);
void Unsubclass();
void ShowWindow(bool bShow = true, bool bTakeFocus = true);
UINT ShowModal();
void Close(UINT nRet = IDOK);
void CenterWindow();
void SetIcon(UINT nRes);
LRESULT SendMessage(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0L);
LRESULT PostMessage(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0L);
void ResizeClient(int cx = -1, int cy = -1);
protected:
virtual LPCTSTR GetWindowClassName() const = 0;
virtual LPCTSTR GetSuperClassName() const;
virtual UINT GetClassStyle() const;
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual void OnFinalMessage(HWND hWnd);
static LRESULT CALLBACK __WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK __ControlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
HWND m_hWnd;
WNDPROC m_OldWndProc;
bool m_bSubclassed;
};
} // namespace DuiLib
#endif // __UIBASE_H__
#include "StdAfx.h"
#ifdef _DEBUG
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
#endif
namespace DuiLib {
/
//
//
void UILIB_API DUI__Trace(LPCTSTR pstrFormat, ...)
{
#ifdef _DEBUG
TCHAR szBuffer[300] = { 0 };
va_list args;
va_start(args, pstrFormat);
::wvnsprintf(szBuffer, lengthof(szBuffer) - 2, pstrFormat, args);
_tcscat(szBuffer, _T("\n"));
va_end(args);
::OutputDebugString(szBuffer);
#endif
}
LPCTSTR DUI__TraceMsg(UINT uMsg)
{
#define MSGDEF(x) if(uMsg==x) return _T(#x)
MSGDEF(WM_SETCURSOR);
MSGDEF(WM_NCHITTEST);
MSGDEF(WM_NCPAINT);
MSGDEF(WM_PAINT);
MSGDEF(WM_ERASEBKGND);
MSGDEF(WM_NCMOUSEMOVE);
MSGDEF(WM_MOUSEMOVE);
MSGDEF(WM_MOUSELEAVE);
MSGDEF(WM_MOUSEHOVER);
MSGDEF(WM_NOTIFY);
MSGDEF(WM_COMMAND);
MSGDEF(WM_MEASUREITEM);
MSGDEF(WM_DRAWITEM);
MSGDEF(WM_LBUTTONDOWN);
MSGDEF(WM_LBUTTONUP);
MSGDEF(WM_LBUTTONDBLCLK);
MSGDEF(WM_RBUTTONDOWN);
MSGDEF(WM_RBUTTONUP);
MSGDEF(WM_RBUTTONDBLCLK);
MSGDEF(WM_SETFOCUS);
MSGDEF(WM_KILLFOCUS);
MSGDEF(WM_MOVE);
MSGDEF(WM_SIZE);
MSGDEF(WM_SIZING);
MSGDEF(WM_MOVING);
MSGDEF(WM_GETMINMAXINFO);
MSGDEF(WM_CAPTURECHANGED);
MSGDEF(WM_WINDOWPOSCHANGED);
MSGDEF(WM_WINDOWPOSCHANGING);
MSGDEF(WM_NCCALCSIZE);
MSGDEF(WM_NCCREATE);
MSGDEF(WM_NCDESTROY);
MSGDEF(WM_TIMER);
MSGDEF(WM_KEYDOWN);
MSGDEF(WM_KEYUP);
MSGDEF(WM_CHAR);
MSGDEF(WM_SYSKEYDOWN);
MSGDEF(WM_SYSKEYUP);
MSGDEF(WM_SYSCOMMAND);
MSGDEF(WM_SYSCHAR);
MSGDEF(WM_VSCROLL);
MSGDEF(WM_HSCROLL);
MSGDEF(WM_CHAR);
MSGDEF(WM_SHOWWINDOW);
MSGDEF(WM_PARENTNOTIFY);
MSGDEF(WM_CREATE);
MSGDEF(WM_NCACTIVATE);
MSGDEF(WM_ACTIVATE);
MSGDEF(WM_ACTIVATEAPP);
MSGDEF(WM_CLOSE);
MSGDEF(WM_DESTROY);
MSGDEF(WM_GETICON);
MSGDEF(WM_GETTEXT);
MSGDEF(WM_GETTEXTLENGTH);
static TCHAR szMsg[10];
::wsprintf(szMsg, _T("0x%04X"), uMsg);
return szMsg;
}
/
//
//
//
//
DUI_BASE_BEGIN_MESSAGE_MAP(CNotifyPump)
DUI_END_MESSAGE_MAP()
static const DUI_MSGMAP_ENTRY* DuiFindMessageEntry(const DUI_MSGMAP_ENTRY* lpEntry,TNotifyUI& msg )
{
CDuiString sMsgType = msg.sType;
CDuiString sCtrlName = msg.pSender->GetName();
const DUI_MSGMAP_ENTRY* pMsgTypeEntry = NULL;
while (lpEntry->nSig != DuiSig_end)
{
if(lpEntry->sMsgType==sMsgType)
{
if(!lpEntry->sCtrlName.IsEmpty())
{
if(lpEntry->sCtrlName==sCtrlName)
{
return lpEntry;
}
}
else
{
pMsgTypeEntry = lpEntry;
}
}
lpEntry++;
}
return pMsgTypeEntry;
}
bool CNotifyPump::AddVirtualWnd(CDuiString strName,CNotifyPump* pObject)
{
if( m_VirtualWndMap.Find(strName) == NULL )
{
m_VirtualWndMap.Insert(strName.GetData(),(LPVOID)pObject);
return true;
}
return false;
}
bool CNotifyPump::RemoveVirtualWnd(CDuiString strName)
{
if( m_VirtualWndMap.Find(strName) != NULL )
{
m_VirtualWndMap.Remove(strName);
return true;
}
return false;
}
bool CNotifyPump::LoopDispatch(TNotifyUI& msg)
{
const DUI_MSGMAP_ENTRY* lpEntry = NULL;
const DUI_MSGMAP* pMessageMap = NULL;
#ifndef UILIB_STATIC
for(pMessageMap = GetMessageMap(); pMessageMap!=NULL; pMessageMap = (*pMessageMap->pfnGetBaseMap)())
#else
for(pMessageMap = GetMessageMap(); pMessageMap!=NULL; pMessageMap = pMessageMap->pBaseMap)
#endif
{
#ifndef UILIB_STATIC
ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
#else
ASSERT(pMessageMap != pMessageMap->pBaseMap);
#endif
if ((lpEntry = DuiFindMessageEntry(pMessageMap->lpEntries,msg)) != NULL)
{
goto LDispatch;
}
}
return false;
LDispatch:
union DuiMessageMapFunctions mmf;
mmf.pfn = lpEntry->pfn;
bool bRet = false;
int nSig;
nSig = lpEntry->nSig;
switch (nSig)
{
default:
ASSERT(FALSE);
break;
case DuiSig_lwl:
(this->*mmf.pfn_Notify_lwl)(msg.wParam,msg.lParam);
bRet = true;
break;
case DuiSig_vn:
(this->*mmf.pfn_Notify_vn)(msg);
bRet = true;
break;
}
return bRet;
}
void CNotifyPump::NotifyPump(TNotifyUI& msg)
{
///遍历虚拟窗口
if( !msg.sVirtualWnd.IsEmpty() ){
for( int i = 0; i< m_VirtualWndMap.GetSize(); i++ ) {
if( LPCTSTR key = m_VirtualWndMap.GetAt(i) ) {
if( _tcsicmp(key, msg.sVirtualWnd.GetData()) == 0 ){
CNotifyPump* pObject = static_cast<CNotifyPump*>(m_VirtualWndMap.Find(key, false));
if( pObject && pObject->LoopDispatch(msg) )
return;
}
}
}
}
///
//遍历主窗口
LoopDispatch( msg );
}
//
///
CWindowWnd::CWindowWnd() : m_hWnd(NULL), m_OldWndProc(::DefWindowProc), m_bSubclassed(false)
{
}
HWND CWindowWnd::GetHWND() const
{
return m_hWnd;
}
UINT CWindowWnd::GetClassStyle() const
{
return 0;
}
LPCTSTR CWindowWnd::GetSuperClassName() const
{
return NULL;
}
CWindowWnd::operator HWND() const
{
return m_hWnd;
}
HWND CWindowWnd::CreateDuiWindow( HWND hwndParent, LPCTSTR pstrWindowName,DWORD dwStyle /*=0*/, DWORD dwExStyle /*=0*/ )
{
return Create(hwndParent,pstrWindowName,dwStyle,dwExStyle,0,0,0,0,NULL);
}
HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, const RECT rc, HMENU hMenu)
{
return Create(hwndParent, pstrName, dwStyle, dwExStyle, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hMenu);
}
HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, int x, int y, int cx, int cy, HMENU hMenu)
{
if( GetSuperClassName() != NULL && !RegisterSuperclass() ) return NULL;
if( GetSuperClassName() == NULL && !RegisterWindowClass() ) return NULL;
m_hWnd = ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName, dwStyle, x, y, cx, cy, hwndParent, hMenu, CPaintManagerUI::GetInstance(), this);
ASSERT(m_hWnd!=NULL);
return m_hWnd;
}
HWND CWindowWnd::Subclass(HWND hWnd)
{
ASSERT(::IsWindow(hWnd));
ASSERT(m_hWnd==NULL);
m_OldWndProc = SubclassWindow(hWnd, __WndProc);
if( m_OldWndProc == NULL ) return NULL;
m_bSubclassed = true;
m_hWnd = hWnd;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(this));
return m_hWnd;
}
void CWindowWnd::Unsubclass()
{
ASSERT(::IsWindow(m_hWnd));
if( !::IsWindow(m_hWnd) ) return;
if( !m_bSubclassed ) return;
SubclassWindow(m_hWnd, m_OldWndProc);
m_OldWndProc = ::DefWindowProc;
m_bSubclassed = false;
}
void CWindowWnd::ShowWindow(bool bShow /*= true*/, bool bTakeFocus /*= false*/)
{
ASSERT(::IsWindow(m_hWnd));
if( !::IsWindow(m_hWnd) ) return;
::ShowWindow(m_hWnd, bShow ? (bTakeFocus ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE) : SW_HIDE);
}
UINT CWindowWnd::ShowModal()
{
ASSERT(::IsWindow(m_hWnd));
UINT nRet = 0;
HWND hWndParent = GetWindowOwner(m_hWnd);
::ShowWindow(m_hWnd, SW_SHOWNORMAL);
::EnableWindow(hWndParent, FALSE);
MSG msg = { 0 };
while( ::IsWindow(m_hWnd) && ::GetMessage(&msg, NULL, 0, 0) ) {
if( msg.message == WM_CLOSE && msg.hwnd == m_hWnd ) {
nRet = msg.wParam;
::EnableWindow(hWndParent, TRUE);
::SetFocus(hWndParent);
}
if( !CPaintManagerUI::TranslateMessage(&msg) ) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
if( msg.message == WM_QUIT ) break;
}
::EnableWindow(hWndParent, TRUE);
::SetFocus(hWndParent);
if( msg.message == WM_QUIT ) ::PostQuitMessage(msg.wParam);
return nRet;
}
void CWindowWnd::Close(UINT nRet)
{
ASSERT(::IsWindow(m_hWnd));
if( !::IsWindow(m_hWnd) ) return;
PostMessage(WM_CLOSE, (WPARAM)nRet, 0L);
}
void CWindowWnd::CenterWindow()
{
ASSERT(::IsWindow(m_hWnd));
ASSERT((GetWindowStyle(m_hWnd)&WS_CHILD)==0);
RECT rcDlg = { 0 };
::GetWindowRect(m_hWnd, &rcDlg);
RECT rcArea = { 0 };
RECT rcCenter = { 0 };
HWND hWndParent = ::GetParent(m_hWnd);
HWND hWndCenter = ::GetWindowOwner(m_hWnd);
::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);
if( hWndCenter == NULL ) rcCenter = rcArea; else ::GetWindowRect(hWndCenter, &rcCenter);
int DlgWidth = rcDlg.right - rcDlg.left;
int DlgHeight = rcDlg.bottom - rcDlg.top;
// Find dialog's upper left based on rcCenter
int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
// The dialog is outside the screen, move it inside
if( xLeft < rcArea.left ) xLeft = rcArea.left;
else if( xLeft + DlgWidth > rcArea.right ) xLeft = rcArea.right - DlgWidth;
if( yTop < rcArea.top ) yTop = rcArea.top;
else if( yTop + DlgHeight > rcArea.bottom ) yTop = rcArea.bottom - DlgHeight;
::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
void CWindowWnd::SetIcon(UINT nRes)
{
HICON hIcon = (HICON)::LoadImage(CPaintManagerUI::GetInstance(), MAKEINTRESOURCE(nRes), IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
ASSERT(hIcon);
::SendMessage(m_hWnd, WM_SETICON, (WPARAM) TRUE, (LPARAM) hIcon);
hIcon = (HICON)::LoadImage(CPaintManagerUI::GetInstance(), MAKEINTRESOURCE(nRes), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
ASSERT(hIcon);
::SendMessage(m_hWnd, WM_SETICON, (WPARAM) FALSE, (LPARAM) hIcon);
}
bool CWindowWnd::RegisterWindowClass()
{
WNDCLASS wc = { 0 };
wc.style = GetClassStyle();
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hIcon = NULL;
wc.lpfnWndProc = CWindowWnd::__WndProc;
wc.hInstance = CPaintManagerUI::GetInstance();
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = GetWindowClassName();
ATOM ret = ::RegisterClass(&wc);
ASSERT(ret!=NULL || ::GetLastError()==ERROR_CLASS_ALREADY_EXISTS);
return ret != NULL || ::GetLastError() == ERROR_CLASS_ALREADY_EXISTS;
}
bool CWindowWnd::RegisterSuperclass()
{
// Get the class information from an existing
// window so we can subclass it later on...
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(WNDCLASSEX);
if( !::GetClassInfoEx(NULL, GetSuperClassName(), &wc) ) {
if( !::GetClassInfoEx(CPaintManagerUI::GetInstance(), GetSuperClassName(), &wc) ) {
ASSERT(!"Unable to locate window class");
return NULL;
}
}
m_OldWndProc = wc.lpfnWndProc;
wc.lpfnWndProc = CWindowWnd::__ControlProc;
wc.hInstance = CPaintManagerUI::GetInstance();
wc.lpszClassName = GetWindowClassName();
ATOM ret = ::RegisterClassEx(&wc);
ASSERT(ret!=NULL || ::GetLastError()==ERROR_CLASS_ALREADY_EXISTS);
return ret != NULL || ::GetLastError() == ERROR_CLASS_ALREADY_EXISTS;
}
LRESULT CALLBACK CWindowWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd* pThis = NULL;
if( uMsg == WM_NCCREATE ) {
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);
pThis->m_hWnd = hWnd;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));
}
else {
pThis = reinterpret_cast<CWindowWnd*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
if( uMsg == WM_NCDESTROY && pThis != NULL ) {
LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
::SetWindowLongPtr(pThis->m_hWnd, GWLP_USERDATA, 0L);
if( pThis->m_bSubclassed ) pThis->Unsubclass();
pThis->m_hWnd = NULL;
pThis->OnFinalMessage(hWnd);
return lRes;
}
}
if( pThis != NULL ) {
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
LRESULT CALLBACK CWindowWnd::__ControlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd* pThis = NULL;
if( uMsg == WM_NCCREATE ) {
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);
::SetProp(hWnd, _T("WndX"), (HANDLE) pThis);
pThis->m_hWnd = hWnd;
}
else {
pThis = reinterpret_cast<CWindowWnd*>(::GetProp(hWnd, _T("WndX")));
if( uMsg == WM_NCDESTROY && pThis != NULL ) {
LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
if( pThis->m_bSubclassed ) pThis->Unsubclass();
::SetProp(hWnd, _T("WndX"), NULL);
pThis->m_hWnd = NULL;
pThis->OnFinalMessage(hWnd);
return lRes;
}
}
if( pThis != NULL ) {
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
LRESULT CWindowWnd::SendMessage(UINT uMsg, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/)
{
ASSERT(::IsWindow(m_hWnd));
return ::SendMessage(m_hWnd, uMsg, wParam, lParam);
}
LRESULT CWindowWnd::PostMessage(UINT uMsg, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/)
{
ASSERT(::IsWindow(m_hWnd));
return ::PostMessage(m_hWnd, uMsg, wParam, lParam);
}
void CWindowWnd::ResizeClient(int cx /*= -1*/, int cy /*= -1*/)
{
ASSERT(::IsWindow(m_hWnd));
RECT rc = { 0 };
if( !::GetClientRect(m_hWnd, &rc) ) return;
if( cx != -1 ) rc.right = cx;
if( cy != -1 ) rc.bottom = cy;
if( !::AdjustWindowRectEx(&rc, GetWindowStyle(m_hWnd), (!(GetWindowStyle(m_hWnd) & WS_CHILD) && (::GetMenu(m_hWnd) != NULL)), GetWindowExStyle(m_hWnd)) ) return;
::SetWindowPos(m_hWnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
}
LRESULT CWindowWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return ::CallWindowProc(m_OldWndProc, m_hWnd, uMsg, wParam, lParam);
}
void CWindowWnd::OnFinalMessage(HWND /*hWnd*/)
{
}
} // namespace DuiLib