1.说明
稍微修改了下QQ示例里面的聊天界面界面,然后把代码扣过来完成了QQ聊天界面部分,效果还可以。
不过自己添加了消息响应:窗口抖动,截屏,字体栏的显示和隐藏
2.代码部分
// QQTalk.h文件
#ifndef __QQ_TALK_H__
#define __QQ_TALK_H__
#include <DuiLib/DuiLibEnv.h>
#include <DuiLib/UIlib.h>
using namespace DuiLib;
#define QQ_TALK_XML _T("chatbox.xml")
class CQQTalk : public CWindowWnd, public INotifyUI
{
public:
CQQTalk();
~CQQTalk();
virtual LPCTSTR GetWindowClassName() const; // CWindowWnd的纯虚函数,必须实现
virtual void Notify( TNotifyUI& msg ); // INotifyUI的纯虚函数,必须实现
// 窗口消息处理回调函数
virtual LRESULT HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam );
private:
// 消息处理函数
LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle);
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle);
LRESULT OnNCActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle);
LRESULT OnNCCalcsize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle);
LRESULT OnNCPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle);
LRESULT OnDestory(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle);
// 控件消息处理函数
void OnNotifyClick(TNotifyUI& msg);
// 获取窗口控件
void GetCtrlFromRes();
// 窗口晃动
void Shake();
// 截屏
void ScreenShot();
protected:
CPaintManagerUI m_paintManager; // 窗口消息类管理对象
private:
// 窗口控件列表
CButtonUI* m_pBtnClose;
CButtonUI* m_pBtnSend;
CButtonUI* m_pBtnCloseBox;
CButtonUI* m_pBtnMinBox;
CButtonUI* m_pBtnMaxBox;
CButtonUI* m_pFontBtn;
CButtonUI* m_pShockBtn;
CButtonUI* m_pScreenShotsbtn;
CButtonUI* m_pHomeBtn;
CRichEditUI* m_pInputRichEdit;
CHorizontalLayoutUI* m_pHorizonLayoutFontbar;
private:
static LPCTSTR m_lpszWndClsName; // 窗口类名
HMODULE m_hScreenShot; // 截屏模块句柄
};
#endif
// QQTalk.cpp文件
#include "QQTalk.h"
#include <exception>
// 截屏导出函数
typedef int (*FnStartScreenCapture)(const char* szAuth, const char* szDefaultSavePath, void* pCallBack, unsigned long hWndNotice, unsigned int noticeMsg);
typedef int (*FnInitScreenCapture)(unsigned long trackerColor, unsigned long editBorderColor, int nTransparent, int flag);
FnStartScreenCapture g_StartScreenCapture = NULL;
FnInitScreenCapture g_InitCapture = NULL;
LPCTSTR CQQTalk::m_lpszWndClsName = _T("QQTalk");
LPCTSTR CQQTalk::GetWindowClassName() const
{
return m_lpszWndClsName;
}
void CQQTalk::Notify( TNotifyUI& msg )
{
if(msg.sType == _T("click"))
{
OnNotifyClick(msg);
}
}
LRESULT CQQTalk::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT lRes = 0;
BOOL bHandle = FALSE;
switch(uMsg)
{
case WM_CREATE: lRes = OnCreate(uMsg, wParam, lParam, bHandle);break;
case WM_NCHITTEST: lRes = OnNcHitTest(uMsg, wParam, lParam, bHandle);break;
case WM_NCACTIVATE: lRes = OnNCActivate(uMsg, wParam, lParam, bHandle);break;
case WM_NCCALCSIZE: lRes = OnNCCalcsize(uMsg, wParam, lParam, bHandle);break;
case WM_NCPAINT: lRes = OnNCPaint(uMsg, wParam, lParam, bHandle);break;
case WM_DESTROY: lRes = OnDestory(uMsg, wParam, lParam, bHandle);break;
default: lRes = FALSE;break;
}
if(bHandle)
{
return lRes;
}
else
{
if( m_paintManager.MessageHandler(uMsg, wParam, lParam, lRes) )
{
return lRes;
}
else
{
return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
}
}
}
LRESULT CQQTalk::OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle )
{
m_paintManager.Init(m_hWnd);
CDialogBuilder builder;
CControlUI* pRoot = builder.Create(QQ_TALK_XML, (UINT)0, NULL, &m_paintManager);
ASSERT(pRoot && "Failed to parse XML");
m_paintManager.AttachDialog(pRoot);
bool bRet = m_paintManager.AddNotifier(this);
GetCtrlFromRes();
bHandle = TRUE;
return 0;
}
LRESULT CQQTalk::OnNCActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle )
{
bHandle = TRUE;
return 0;
}
LRESULT CQQTalk::OnNCCalcsize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle )
{
bHandle = TRUE;
return 0;
}
LRESULT CQQTalk::OnNCPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle )
{
bHandle = TRUE;
return 0;
}
LRESULT CQQTalk::OnNcHitTest( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle )
{
bHandle = TRUE;
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
::ScreenToClient(*this, &pt);
RECT rcClient;
::GetClientRect(*this, &rcClient);
RECT rcCaption = m_paintManager.GetCaptionRect();
if( pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom ) {
CControlUI* pControl = static_cast<CControlUI*>(m_paintManager.FindControl(pt));
if( pControl && _tcscmp(pControl->GetClass(), _T("ButtonUI")) != 0 &&
_tcscmp(pControl->GetClass(), _T("OptionUI")) != 0 &&
_tcscmp(pControl->GetClass(), _T("TextUI")) != 0 )
return HTCAPTION;
}
return HTCLIENT;
}
LRESULT CQQTalk::OnDestory( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle )
{
::PostQuitMessage(0L);
bHandle = TRUE;
return 0;
}
void CQQTalk::GetCtrlFromRes()
{
m_pBtnClose = static_cast<CButtonUI*>(m_paintManager.FindControl(_T("closebtn")));
m_pBtnSend = static_cast<CButtonUI*>(m_paintManager.FindControl(_T("sendbtn")));
m_pBtnCloseBox = static_cast<CButtonUI*>(m_paintManager.FindControl(_T("closebtn_box")));
m_pBtnMinBox = static_cast<CButtonUI*>(m_paintManager.FindControl(_T("minbtn_box")));
m_pBtnMaxBox = static_cast<CButtonUI*>(m_paintManager.FindControl(_T("maxbtn_box")));
m_pFontBtn = static_cast<CButtonUI*>(m_paintManager.FindControl(_T("fontbtn")));
m_pShockBtn = static_cast<CButtonUI*>(m_paintManager.FindControl(_T("shockbtn")));
m_pScreenShotsbtn = static_cast<CButtonUI*>(m_paintManager.FindControl(_T("screenshotsbtn")));
m_pHomeBtn = static_cast<CButtonUI*>(m_paintManager.FindControl(_T("home")));
m_pHorizonLayoutFontbar = static_cast<CHorizontalLayoutUI*>(m_paintManager.FindControl(_T("fontbar")));
m_pInputRichEdit = static_cast<CRichEditUI*>(m_paintManager.FindControl(_T("input_richedit")));
m_pBtnMaxBox->SetEnabled(false);
m_pHorizonLayoutFontbar->SetVisible(false);
}
void CQQTalk::OnNotifyClick( TNotifyUI& msg )
{
if( msg.pSender == m_pBtnClose || msg.pSender == m_pBtnCloseBox)
{
PostQuitMessage(0);
return;
}
if( msg.pSender == m_pFontBtn )
{
m_pHorizonLayoutFontbar->SetVisible(!m_pHorizonLayoutFontbar->IsVisible());
return ;
}
if( msg.pSender == m_pShockBtn )
{
Shake();
return;
}
if(msg.pSender == m_pScreenShotsbtn)
{
ScreenShot();
return;
}
if ( msg.pSender == m_pHomeBtn)
{
ShellExecute(NULL, _T("open"), _T("http://blog.csdn.net/arbboter"), NULL,NULL, SW_MAXIMIZE);
return;
}
if( msg.pSender == m_pBtnSend )
{
// 直接弹出消息框后果很严重
//MessageBox(m_hWnd, _T("少年你想多了!"), _T("Message from : Arbboter"), MB_OK | MB_ICONWARNING);
m_pInputRichEdit->SetSel(0,-1);
m_pInputRichEdit->Clear();
m_pInputRichEdit->AppendText(_T("想发送消息?少年你想多了!"));
return;
}
if( msg.sType == _T("click"))
{
m_pInputRichEdit->SetSel(0,-1);
m_pInputRichEdit->Clear();
m_pInputRichEdit->AppendText(_T("呵呵?少年你想多了!"));
return;
}
}
void CQQTalk::Shake()
{
int ty=3;
int nFre = 30;
CRect m_rect;
GetWindowRect(this->m_hWnd, &m_rect);
int recordy=m_rect.left;
int recordx=m_rect.top;
for(int i=0;i<3;i++)
{
m_rect.left=recordy;
m_rect.top=recordx;
m_rect.top = m_rect.top + ty;
m_rect.left = m_rect.left - ty;
SetWindowPos(this->m_hWnd, NULL,m_rect.left,m_rect.top,0,0,SWP_NOSIZE );
Sleep(nFre);
m_rect.top = m_rect.top -ty;
SetWindowPos(this->m_hWnd, NULL,m_rect.left,m_rect.top,0,0,SWP_NOSIZE );
Sleep(nFre);
m_rect.top = m_rect.top -2*ty;
SetWindowPos(this->m_hWnd, NULL,m_rect.left,m_rect.top,0,0,SWP_NOSIZE );
Sleep(nFre);
m_rect.left=m_rect.left+ty;
SetWindowPos(this->m_hWnd, NULL,m_rect.left,m_rect.top,0,0,SWP_NOSIZE );
Sleep(nFre);
m_rect.left=m_rect.left+2*ty;
SetWindowPos(this->m_hWnd, NULL,m_rect.left,m_rect.top,0,0,SWP_NOSIZE );
Sleep(nFre);
m_rect.top = m_rect.top + ty;
SetWindowPos(this->m_hWnd, NULL,m_rect.left,m_rect.top,0,0,SWP_NOSIZE );
Sleep(nFre);
m_rect.top=m_rect.top+2*ty;
SetWindowPos(this->m_hWnd, NULL,m_rect.left,m_rect.top,0,0,SWP_NOSIZE );
SetWindowPos(this->m_hWnd, NULL,recordy,recordx,0,0,SWP_NOSIZE );
Sleep(nFre);
}
}
void CQQTalk::ScreenShot()
{
g_StartScreenCapture("niuniu", "", NULL, NULL, NULL);
}
CQQTalk::CQQTalk()
{
// 初始化截屏,借用别人的截图模块
m_hScreenShot = LoadLibrary(_T("NiuniuCapture.dll"));
if(m_hScreenShot)
{
g_StartScreenCapture = (FnStartScreenCapture)GetProcAddress(m_hScreenShot, "StartScreenCapture");
g_InitCapture = (FnInitScreenCapture)GetProcAddress(m_hScreenShot, "InitScreenCapture");
//设置截图边框的样式
g_InitCapture(RGB(255, 0, 0), RGB(0, 174, 255), 180, 0);
}
}
CQQTalk::~CQQTalk()
{
if(m_hScreenShot)
{
FreeLibrary(m_hScreenShot);
m_hScreenShot = NULL;
}
}
// main.cpp
// 测试文件
#include "QQTalk.h"
int WINAPI wWinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPWSTR lpCmdLine, __in int nShowCmd )
{
// 初始化CPaintManagerUI
CPaintManagerUI::SetInstance(hInstance);
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("skin"));
CPaintManagerUI::SetResourceZip(_T("QQRes.zip"));
// 这一步可选
// CoInitialize是Windows提供的API函数
// 用来告诉 Windows以单线程的方式创建com对象
HRESULT Hr = ::CoInitialize(NULL);
if( FAILED(Hr) ) return 0;
// 创建一个QQ对话界面
CQQTalk* pQQTalkDlg = new CQQTalk();
pQQTalkDlg->Create(NULL, _T("和XXX的对话"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
pQQTalkDlg->CenterWindow();
pQQTalkDlg->ShowModal();
CPaintManagerUI::MessageLoop();
delete pQQTalkDlg; pQQTalkDlg = NULL;
// 逆初始化
::CoUninitialize();
return 0;
}