关于网站建设的外文翻译,营销推广是干什么的,创建站点是什么意思,智慧团建电脑版登录官网文章目录 通过动态链表实现游戏角色动态增加CMemoryDC.hCFlashDlg.hCFlashDlg.cpp WM_ERASEBKGND背景刷新的原理RegisterClass注册窗口与框架程序开发CFrameRegister 通过动态链表实现游戏角色动态增加
CMemoryDC.h #pragma once#include resource.h/*内存DC类简介… 文章目录 通过动态链表实现游戏角色动态增加CMemoryDC.hCFlashDlg.hCFlashDlg.cpp WM_ERASEBKGND背景刷新的原理RegisterClass注册窗口与框架程序开发CFrameRegister 通过动态链表实现游戏角色动态增加
CMemoryDC.h #pragma once#include resource.h/*内存DC类简介 1、BOOL LoadBitmap(UINT nBitmapID,CDC* pDC NULL)从资源中按照按位图ID加载位图2、BOOL LoadFile(LPCTSTR sFile, CDC* pDC NULL)从exe外部加载图片调用LoadImage3、BOOL Create(int cx, int cy, CDC* pDC NULL)创建空白位图默认是全黑4、总共有4种构造函数包含以上3种还有空构造CMemoryDC(UINT nBitmapID)//从资源按照位图编号来加载CMemoryDC(LPCTSTR sFile, CDC* pDC NULL)//从exe外部加载CMemoryDC(int cx, int cy, CDC* pDCNULL)//指定高宽创建空白位图5、void MakeRgn(CRgn r,COLORREF col)生成透明区域6、int GetWidth() constint GetHeight() const方便地获取图片高宽7、透明显示BitTrans和StrecthTrans*/class CMemoryDC :public CDC{CSize m_size;public:CMemoryDC();int GetWidth() const{return m_size.cx;}int GetHeight() const{return m_size.cy;}CSize GetSize() const{return m_size;}void BitTrans(int nXDest, // 目标起点Xint nYDest, // 目标起点Yint nWidthDest, // 目标宽度int nHeightDest,// 目标高度CDC* pDC, // 目标DCint nXSrc, // 来源起点Xint nYSrc, // 来源起点YCOLORREF crTrans// 透明色){CMemoryDC dcImage(nWidthDest, nHeightDest, pDC);//临时DCCBitmap bmpMask;bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); // 创建单色掩码位图CDC dcMask;//掩码DC dcMask.CreateCompatibleDC(pDC);dcMask.SelectObject(bmpMask);//将载入位图的内存DC中的位图拷贝到临时DC中dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);// 设置临时DC的透明色dcImage.SetBkColor(crTrans);//掩码DC的透明区域为白色其它区域为黑色dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, dcImage, 0, 0, SRCCOPY);//临时DC透明区域为黑色其它区域保持不变dcImage.SetBkColor(RGB(0, 0, 0));dcImage.SetTextColor(RGB(255, 255, 255));dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, dcMask, 0, 0, SRCAND);// 目标DC透明部分保持屏幕不变其它部分变成黑色pDC-SetBkColor(RGB(255, 255, 255));pDC-SetTextColor(RGB(0, 0, 0));pDC-BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, dcMask, 0, 0, SRCAND);pDC-BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, dcImage, 0, 0, SRCPAINT);}void StretchTrans(int nXDest, // 目标起点Xint nYDest, // 目标起点Yint nWidthDest, // 目标宽度int nHeightDest, // 目标高度CDC* pDC, // 目标DCint nXSrc, // 来源起点Xint nYSrc, // 来源起点Yint nWidthSrc, // 来源宽度int nHeightSrc, // 来源高度COLORREF crTrans // 透明色){CMemoryDC dcImage(nWidthDest, nHeightDest, pDC);//临时DCCBitmap bmpMask;// 创建单色掩码位图bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);CDC dcMask;dcMask.CreateCompatibleDC(pDC);dcMask.SelectObject(bmpMask);// 将载入位图的内存DC中的位图拷贝到临时DC中if (nWidthDest nWidthSrc nHeightDest nHeightSrc)dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);elsedcImage.StretchBlt(0, 0, nWidthDest, nHeightDest,this, nXSrc, nYSrc, nWidthSrc, nHeightSrc, SRCCOPY);// 设置临时DC的透明色dcImage.SetBkColor(crTrans);//掩码DC的透明区域为白色其它区域为黑色dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, dcImage, 0, 0, SRCCOPY);//临时DC透明区域为黑色其它区域保持不变dcImage.SetBkColor(RGB(0, 0, 0));dcImage.SetTextColor(RGB(255, 255, 255));dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, dcMask, 0, 0, SRCAND);// 目标DC透明部分保持屏幕不变其它部分变成黑色pDC-SetBkColor(RGB(255, 255, 255));pDC-SetTextColor(RGB(0, 0, 0));pDC-BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, dcMask, 0, 0, SRCAND);pDC-BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, dcImage, 0, 0, SRCPAINT);}//创建空位图BOOL Create(int cx, int cy, CDC* pDc NULL){if (!CreateCompatibleDC(NULL))return FALSE;CBitmap bmp;if (pDc){if (!bmp.CreateCompatibleBitmap(pDc, cx, cy)) {DeleteDC();return FALSE;}}else{if (!bmp.CreateCompatibleBitmap(CClientDC(NULL), cx, cy)){DeleteDC();return FALSE;}}this-SelectObject(bmp);m_size.SetSize(cx, cy);return TRUE;}//加载一张exe外部位图BOOL LoadFile(LPCTSTR sFile, CDC* pDC NULL){HBITMAP hBitmap (HBITMAP)LoadImage(NULL, sFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);if (!hBitmap)return FALSE; if (!CreateCompatibleDC(NULL)){DeleteObject(hBitmap);return FALSE;}SelectObject(hBitmap);BITMAP bm;GetObject(hBitmap, sizeof(bm), bm);m_size.SetSize(bm.bmWidth, bm.bmHeight);DeleteObject(hBitmap);return TRUE;}//加载一张资源位图BOOL LoadBitmap(UINT nBitmapID, CDC* pDC NULL){if (!CreateCompatibleDC(NULL))return FALSE;CBitmap bmp;if (!bmp.LoadBitmap(nBitmapID)){DeleteDC();return FALSE;}SelectObject(bmp);BITMAP bm;bmp.GetBitmap(bm);m_size.SetSize(bm.bmWidth, bm.bmHeight);return TRUE;}CMemoryDC(UINT nBitmapID){LoadBitmap(nBitmapID);}CMemoryDC(LPCTSTR sFile,CDC* pDC NULL){LoadFile(sFile, pDC);}CMemoryDC(int cx,int cy,CDC* pDCNULL){Create(cx, cy, pDC);}void MakeRgn(CRgn r, COLORREF col){r.CreateRectRgn(0, 0, 0, 0);int i -1, cx m_size.cx;int j -1, cy m_size.cy;while (jcy){i -1;while (icx){if (GetPixel(i, j) ! col){CRgn r1;r1.CreateRectRgn(i, j, i 1, j 1); //1*1像素r.CombineRgn(r, r1, RGN_OR);}}}}};CFlashDlg.h
#pragma once
#include CMemoryDC.h
class CCFlashDlg : public CDialogEx{ struct sData {int nIndex;CPoint pos, dir{ 5,5 };};CListsData m_list; //使用动态链表实现 角色的动态增加
// 构造enum {Fly_nCount 7}; //图片总数CMemoryDC m_dcBack{_T(./res/back.bmp)}; //背景图片CMemoryDC m_dcFlys[Fly_nCount]; //蝴蝶CRgn m_rs[Fly_nCount]; //取出背景颜色void LoadPictures();CDC m_dc; //作一个缓冲dc// 实现
protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()
public:afx_msg void OnTimer(UINT_PTR nIDEvent);afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnSize(UINT nType, int cx, int cy);afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};CFlashDlg.cpp
#include pch.h
#include framework.h
#include CFlash.h
#include CFlashDlg.h
#include afxdialogex.h#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CCFlashDlg::CCFlashDlg(CWnd* pParent /*nullptr*/): CDialogEx(IDD_CFLASH_DIALOG, pParent)
{m_hIcon AfxGetApp()-LoadIcon(IDR_MAINFRAME);
}void CCFlashDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CCFlashDlg, CDialogEx)ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_WM_TIMER()ON_WM_LBUTTONDOWN()ON_WM_SIZE()ON_WM_ERASEBKGND()
END_MESSAGE_MAP()BOOL CCFlashDlg::OnInitDialog()
{CDialogEx::OnInitDialog();int cx GetSystemMetrics(SM_CXSCREEN);int cy GetSystemMetrics(SM_CYSCREEN);SetWindowPos(NULL, 0, 0, cx/2, cy/2, SWP_NOZORDER);LoadPictures(); SetTimer(1, 16, NULL);srand((int)time(NULL));return TRUE; // 除非将焦点设置到控件否则返回 TRUE
}void CCFlashDlg::OnPaint()
{CPaintDC dc(this); // 用于绘制的设备上下文CRect rect;GetClientRect(rect);m_dc.SetStretchBltMode(STRETCH_HALFTONE); //拉伸图片质量的m_dc.StretchBlt(0, 0, rect.Width(), rect.Height(), m_dcBack, 0, 0, m_dcBack.GetWidth(), m_dcBack.GetHeight(), SRCCOPY);CMemoryDC mdc(300,280); //创建默认的黑色if (mdc.GetSafeHdc())m_dc.BitBlt(200, 150, 300, 280, mdc, 0, 0, SRCCOPY);//CRgn r;//r.CreateRectRgn(0, 0, 0, 0); //基址//r.CopyRgn(m_rsm_nIndex); //往那个跑先复制出来 不要破坏它 形状//r.OffsetRgn(m_pos); //你要输出到那个位置//dc.SelectObject(r);auto pos m_list.GetHeadPosition();int i 0;while (pos){sData d m_list.GetNext(pos);auto pDC m_dcFlys d.nIndex;pDC-BitTrans(d.pos.x, d.pos.y, pDC-GetWidth(), pDC-GetHeight(), m_dc, 0, 0, 0xff00ff);if (d.nIndex Fly_nCount)d.nIndex 0 ;d.pos.Offset(d.dir); if (d.pos.x m_dcFlys-GetWidth() rect.right || d.pos.x 0)d.dir.x * -1;if (d.pos.y m_dcFlys-GetHeight() rect.bottom || d.pos.y 0)d.dir.y * -1;CString str;str.Format(_T(%d), i);m_dc.TextOut(d.pos.x,d.pos.y,str);} //闪烁 是因为交替输出 dc.BitBlt(0, 0, rect.Width(), rect.Height(), m_dc, 0, 0, SRCCOPY); //双缓冲技术 防止闪烁 采用一次性输出全部由m_dc输出
}void CCFlashDlg::LoadPictures() {int i -1;CString str;while (i_countof(m_dcFlys)) {str.Format(_T(./res/%03d.bmp), i 1);m_dcFlys[i].LoadFile(str);m_dcFlys[i].MakeRgn(m_rs[i],0x00ff00ff);}
}
void CCFlashDlg::OnTimer(UINT_PTR nIDEvent)
{Invalidate(TRUE); //制造了闪烁 因为前景输出 会触发再一次的交替输出CDialogEx::OnTimer(nIDEvent);
}void CCFlashDlg::OnLButtonDown(UINT nFlags, CPoint point) {sData d;d.nIndex rand() % Fly_nCount;int n rand() % 2 ? 1 : -1;d.dir.x 5 * n;n rand() % 2 ? 1 : -1;d.dir.y 5 * n;d.pos point;d.pos.x - m_dcFlys-GetWidth() / 2; //中心点d.pos.y - m_dcFlys-GetHeight() / 2; //中心点m_list.AddTail(d);CDialogEx::OnLButtonDown(nFlags, point);
}void CCFlashDlg::OnSize(UINT nType, int cx, int cy)
{CDialogEx::OnSize(nType, cx, cy);m_dc.DeleteDC();m_dc.CreateCompatibleDC(NULL);CBitmap bmp;bmp.CreateBitmap(cx, cy, 1, 32, NULL);m_dc.SelectObject(bmp);
}
BOOL CCFlashDlg::OnEraseBkgnd(CDC* pDC)
{return TRUE; //给夺权了
}WM_ERASEBKGND背景刷新的原理 WM_ERASEBKGND是一种消息类型它是在窗口需要重绘背景时发送给窗口的。背景刷新的原理是在窗口绘制之前系统首先向窗口发送WM_ERASEBKGND消息窗口可以在处理此消息时进行背景擦除操作即清除原有的背景后。系统会发送WM_PAINT消息窗口可以在处理此消息时进行绘制操作即绘制新的背景。 具体的背景刷新流程如下
当窗口需要重绘背景时系统发送WM_ERASEBKGND消息给窗口。窗口接收到WM_ERASEBKGND消息后可以执行背景擦除操作清除原有的背景。常见的擦除操作包括用背景色填充窗口区域、绘制背景图片等。完成背景擦除后窗口可以返回非零值表示背景已经擦除完毕。系统接收到非零返回值后发送WM_PAINT消息给窗口。窗口接收到WM_PAINT消息后可以执行绘制操作即绘制新的背景。绘制完成后窗口可以调用ValidateRect或InvalidateRect函数通知系统该区域已经被绘制完成系统不再发送WM_PAINT消息。
通过以上流程窗口可以在接收到WM_ERASEBKGND和WM_PAINT消息时分别进行背景擦除和绘制操作实现背景的刷新。
RegisterClass注册窗口与框架程序开发
classname注册窗口类型名有3种方式注册 a)原始APIATOM RegisterClass(const WNDCLASS *lpWndClass); 注册窗口类型 b)MFC封装之后叫做AfxRegisterClass类似于AfxMessageBox封装了MessageBox(API) c)MFC再次封装了一个真正的简易注册函数叫做AfxRegisterWndClass 返回值是自动生成字符串字符串的内容包括三要素的句柄sprintf生成的文字
注册的内容主要包括背景颜色图标光标另外还有的类型包含有菜单
typedef struct tagWNDCLASS {UINT style;WNDPROC lpfnWndProc;int cbClsExtra;int cbWndExtra;HINSTANCE hInstance;HICON hIcon;HCURSOR hCursor;HBRUSH hbrBackground;LPCTSTR lpszMenuName;LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;typedef struct tagWNDCLASSEX {UINT cbSize;UINT style;WNDPROC lpfnWndProc;int cbClsExtra;int cbWndExtra;HINSTANCE hInstance;HICON hIcon;HCURSOR hCursor;HBRUSH hbrBackground;LPCTSTR lpszMenuName;LPCTSTR lpszClassName;HICON hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;LPCTSTR AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor 0, HBRUSH hbrBackground 0, HICON hIcon 0
);AfxRegisterClass比API就是多了GetClassInfo探测一下是否已注册过了。
BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass) {WNDCLASS wndcls;if (GetClassInfo(lpWndClass-hInstance, lpWndClass-lpszClassName,wndcls)){return TRUE; // class already registered}if (!RegisterClass(lpWndClass)){TRACE(traceAppMsg, 0, _T(Cant register window class named %Ts\n),lpWndClass-lpszClassName);return FALSE;}注册的背景色的原理 a)RegisterClass指定的背景色依靠什么输出的呢 b)WM_ERASEBKGND消息是默认的背景输出管理消息。 c)WM_ERASEBKGND消息对比WM_PAINT是微软设计的前景和背景管理消息。 d)他当年设计的原理是想要背景覆盖前景方便刷新。 但是这个设计可能会制造闪烁问题 解决办法 a)Invalidate函数代入TRUE表示先触发WM_ERASEBKGRND再触发WM_PAINT消息。 b)Invalidate函数代入FALSE表示不触发WM_ERASEBKGRND只触发WM_PAINT消息。 c)因此好彻底解决闪烁问题还要注意尽量Invalidate代入FALSE d)另外也尽量把WM_ERASEBKGRND消息映射函数清空只留WM_PAINT 的输出。
inline static bool IsWindowClassRegistered(LPCTSTR sClass) //用于检测注册类名 是否会重复
{WNDCLASSEX wcex;return (GetClassInfoEx(NULL, sClass, wcex) ! 0);
}BOOL CLadderCtrl::OnEraseBkgnd(CDC* pDC) // RegisterClass(wc); wc.hbrBackground m_brBack; 背景颜色依靠这个消息输出的
{return CWnd::OnEraseBkgnd(pDC); //默认背景输出
}BOOL CLadderCtrl::Create(DWORD dwStyle, CRect rect, CWnd* pParent, int nID)
{if (!IsWindowClassRegistered(_T(Ladder_XQ))) //用于判断注册类名会不会重复{WNDCLASS wc { CS_HREDRAW | CS_VREDRAW }; //注册窗口类型名wc.hCursor theApp.LoadStandardCursor(IDC_HAND);wc.hbrBackground m_brBack;wc.lpszClassName _T(Ladder_XQ);wc.lpfnWndProc ::DefWindowProc;RegisterClass(wc);}return CWnd::Create(_T(Ladder_XQ), NULL, dwStyle, rect, pParent, nID);
}BOOL Clvxin21Dlg::OnEraseBkgnd(CDC* pDC)
{ CRect rect;GetClientRect(rect);pDC-FillSolidRect(rect, GetSysColor(COLOR_BTNFACE));return TRUE;
}CFrameRegister
MFC环境下创建框架窗口的必备条件 a)InitInstance必须return TRUE; b)theApp.m_pMainWnd 必须指向主窗口对象地址 c)主窗口对象必须是堆空间或者生命期足够。
#include CApp.h
#include CMainFrame.h
CApp thApp;//CWnd* pFrame new CWnd;cant use for desktop or pop-up windows (use CreateEx instead) create不允许用于创建主窗口
//pFrame-Create(NULL, _T(我的世界), WS_VISIBLE, CRect(100, 100, 800, 600), NULL, 9999);//CWnd* pFrame new CWnd;
使用CreatEx时 首先要 make sure the default window class is registered no WNDCLASS provided - use child window default 没有的默认为子窗口创建
//pFrame-CreateEx(0, NULL, _T(我的世界), WS_VISIBLE, CRect(100, 100, 800, 600), NULL, 9999);BOOL CApp::InitInstance(){/*LPCTSTR sClass _T(MY_WORLD);WNDCLASS wc{ CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS };wc.lpfnWndProc ::DefWindowProc;wc.lpszClassName sClass;wc.hCursor LoadStandardCursor(IDC_CROSS);wc.hIcon LoadStandardIcon(IDI_INFORMATION);wc.hbrBackground (HBRUSH)GetStockObject(LTGRAY_BRUSH);RegisterClass(wc);*/auto pFrame new CMainFrame;BOOL b pFrame-CreateEx(0, NULL, _T(我的世界),WS_VISIBLE | WS_MAXIMIZEBOX |WS_MINIMIZEBOX| WS_SYSMENU, 100, 100, 800, 600, NULL, NULL);m_pMainWnd pFrame;return TRUE;
}#include CMainFrame.h
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT cs)
{//if (!CWnd::PreCreateWindow(cs)) //给子框架用来注册的对主框架不好使// return FALSE;cs.lpszClass AfxRegisterWndClass(0); //自己添加的使用的AfxRegisterWndClass 也可以继续在添加属性 预处理return CWnd::PreCreateWindow(cs);
}