VC++开发技术总结

VC开发技术总结
VC++开发技术总结_第1张图片

1.内存分配和申请
GlobalAlloc,GlobalLock,GlobalUnLock
GMEM_FIXED 分配一个固定内存块
GMEM_MOVEABLE 分配一个可移动内存块
GMEM_DISCARDABLE 分配一个可丢弃内存块
GMEM_NOCOMPACT 堆在这个函数调用期间不进行累积
GMEM_NODISCARD 函数调用期间不丢弃任何内存块
GMEM_ZEROINIT 新分配的内存块全部初始化成零
2.数据类型转换
(1)CString和LPCTSTR之间的转换
CString转LPCTSTR:
CString str;

LPCTSTR lpData = str.GetBuffer();
str = lpData;

(2)CString和LPCTSTR之间的转换

3.CDialogEx::OnPaint()问题
正常情况下,CDialogEx::OnPaint()执行没有问题;
当对DC操作有误时,CDialogEx::OnPaint()执行会报错,这时需要屏蔽不执行,否则会引起winhand.cpp line 20 Assert错误。
4.Message问题
(1)清除消息队列:
连续打开2个对话窗,则中间需要清除消息队列,否则可能出现问题:
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
};
(2)WM_PAINT不能被REMOVE,需要Dispatch:
if (msg.message=WM_PAINT)
::DispatchMessage(&msg);
(3)PeekMessage
SetMessageQueue
DispatchMessage
TranslateMessage
GetMessage
PostMessage
PostThreadMessage
PostQuitMessage
SendMessage
SendDlgItemMessage
SendMessageTimeout
SendNotifyMessage
SendMessageCallback
BroadcastSystemMessage
BroadcastSystemMessageEx
GetQueueStatus
InSendMessage
ReplyMessage
5.OCX组件问题
1)注册问题
在WIN10下,批处理文件a.bat以管理员身份运行:
g:
cd\work\MFCActiveXControl2\Debug
regsvr32 /u MFCActiveXControl2.ocx
regsvr32 MFCActiveXControl2.ocx
cmd
6.ReleaseDC()和DeleteDC()问题
GetDC()必须与ReleaseDC()对应,也不能调用DeleteDC(),否则内存出现泄漏。
CreateDC()必须调用DeleteDC()
7.HBITMAP、CBitmap、BITMAP三者之间的关系
HBITMAP是图片句柄,类CBitmap对HBITMAP进行了封装,BITMAP是一个结构体,定义位图的
HBITMAP是图片句柄,类CBitmap对HBITMAP进行了封装,BITMAP是一个结构体,定义位图的信息(如宽度和高度等)。
CBitmap::Attach(),将HBITMAP转换成CBitmap。
CBitmap::GetBitmap(),将位图信息保存在BITMAP 结构中。
CBitmap::GetObject(),从HBITMAP句柄中获取BITMAP结构。
BitBlt()将内存DC中的内容按1:1复制到当前DC中。
StretchBlt()对图像进行伸缩变换后,将内存DC中的内容复制到当前DC中。
8.CDC 和 HDC关系
// CDC -> HDC ///
CDC* pCDC = this->GetDC() ;
HDC hDC;

// 第1种获取方法
hDC = pCDC->GetSafeHdc();
// 第2种获取方法
dc.Attach(hDC);
// HDC -> CDC ///
HDC hDC;
CDC *pCDC = CDC::FromHandle(hDC);
9.进程间通信
Linux的进程间通信方法有管道(Pipe)和有名管道(FIFO)、信号(Signal)、消息队列(Message Queue)、共享内存(Shared Memory)、信号量(Semaphore)、套接字(Socket)等。
10.消息发送
1)机器之间发送接收消息(unix平台):
#include
#include
SERVER:
//通过ftok函数得到指定的ID。
key_t key = ftok(".", 111); //第二个参数随便给
if(key == -1)
{
perror(“ftok 创建失败”);
exit(-1);
}
cout << “通过ftok函数创建指定的ID” << endl;
//创建一个消息队列对象
int msgid = msgget(key, IPC_CREAT|IPC_EXCL|0777);
if(msgid == -1)
{
perror(“创建这个消息队列失败!”);
exit(-1);
}
cout << “创建talker消息队列成功!” << endl;
cout << “这个队列的ID: " << msgid << endl;
//发送消息
int res = msgsnd(msgid, “Hello Msg!”, 10, 0);
if(res == -1)
{
perror(“消息发送失败:”);
exit(-1);
}
cout << “消息发送成功:server—>” << endl;
CLIENT:
//通过ftok函数得到指定的ID。
key_t key = ftok(”.", 111); //第二个参数随便给
if(key == -1)
{
perror(“ftok 获取失败”);
exit(-1);
}
cout << “通过ftok函数得到指定的ID” << endl;
//创建一个消息队列对象
int msgid = msgget(key, 0);
if(msgid == -1)
{
perror(“创建这个消息队列失败!”);
exit(-1);
}
cout << “创建lisenter消息队列成功!” << endl;
cout << "这个队列的ID: " << msgid << endl;
//存放接收的消息
char buffer[128];
//接收消息
int res = msgrcv(msgid, buffer, 128, 0, 0);
if(res == -1)
{
perror(“消息接收失败:”);
exit(-1);
}
cout << “消息接收成功:client->” << buffer << endl;
2)窗口之间消息发送接收
// 同步
BOOL PostMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
需要一个整个系统唯一的消息,可以调用 SDK 函数 RegisterWindowMessage 并使用 ON_REGISTER_MESSAGE 宏指令取代 ON_MESSAGE 宏指
// 广域发送消息 HWND_BROADCAST ((HWND)0xffff),
LRESULT Res=::SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

3)窗口句柄和窗口类
this->GetSafeHwnd() 与 this->m_hWnd 相等.
对话框中,有的控件不能使用,否则在VS2013中报错
箭头↓→↑←←↑→↓
AfxGetMainWnd()->m_hWnd;

CWnd * pCWnd;
HWND Handle;
pCWnd=FromHandle(Handle);
Handle=GetSafeHwnd(pCWnd);
11.下拉框的高度问题

//************* 设置2个下拉框的高度 **********************//
CRect rc;
m_ComboBox_Factory.GetClientRect(&rc);
m_ComboBox_Factory.SetWindowPos(NULL, 0, 0, rc.Width(), rc.Height() + 100, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);

m_ComboBox_Protocol.GetClientRect(&rc);
m_ComboBox_Protocol.SetWindowPos(NULL, 0, 0, rc.Width(), rc.Height() + 100, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW);

12.ListControl问题
高亮选择
m_listControl_files.SetFocus();
m_listControl_files.SetItemState(0, LVNI_SELECTED, LVNI_SELECTED);

// 以下不能达到预期效果,原因待查… …
NMLISTVIEW nmlv;
memset(&nmlv, 0, sizeof (nmlv));
nmlv.hdr.hwndFrom = m_listControl_files.m_hWnd;
nmlv.hdr.idFrom = m_listControl_files.GetDlgCtrlID();

nmlv.hdr.code = LVN_ITEMCHANGED;
nmlv.iItem = 7;
nmlv.iSubItem = 0;
nmlv.uNewState = 3;
nmlv.uOldState = 0;
nmlv.uChanged = LVIF_STATE;
nmlv.lParam = 0;
m_listControl_files.GetParent()->SendMessage(WM_NOTIFY, nmlv.hdr.idFrom, (LPARAM)(&nmlv));
m_listControl_files.SetFocus();

13.资源 – 菜单,字符串,图标
CMenu* menu = GetMenu();
menu->CheckMenuItem(2052, MF_BYCOMMAND | MF_CHECKED);//设置选择状态

CString strAboutMenu;

CMenu* pSysMenu = GetSystemMenu(FALSE);
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

BOOL bNameValid;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);

HICON m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
SetIcon(m_hIcon, TRUE);			// 设置大图标
SetIcon(m_hIcon, FALSE);		// 设置小图标

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

14.当前模块,线程,进程
//得到当前程序的路径;
wchar_t strPath[100];
GetModuleFileName(NULL, strPath, 100);

STARTUPINFO StartInfo;
PROCESS_INFORMATION procStruct;
memset(&StartInfo, 0, sizeof(STARTUPINFO));
StartInfo.cb = sizeof(STARTUPINFO);

if (CreateProcess((LPCTSTR)strPath, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &StartInfo, &procStruct))
{
	CloseHandle(procStruct.hProcess);
	CloseHandle(procStruct.hThread);
}

15.鼠标位置 – 鼠标单击对象
CPoint point;
GetCursorPos(&point); //获取当前光标的位置,以便使得菜单可以跟随光标
ScreenToClient(&point); //得到窗体的控件句柄
CWnd* pWnd = (CWnd*)ChildWindowFromPoint(point);

if (pWnd != NULL){
}

16.常用API函数
::GetCurrentDirectory(MAX_PATHLENGTH, des.GetBuffer(MAX_PATHLENGTH));
GetPrivateProfileString(TEXT(“ExeFilePath”), TEXT(“ControlPanel”), TEXT(“TestApplication.exe”), SName.GetBuffer(MAX_PATHLENGTH), MAX_PATHLENGTH, des);

pParentWnd->SetRedraw(false);
pPictureControl->ShowWindow(true);

4)界面控件, 刷新等

TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pTTTStruct;

pTTT->hinst = AfxGetResourceHandle();

CStaticExt* pPictureControl = (CStaticExt*)GetDlgItem(nID);

CException* e;
e->Delete();

UpdateWindow( );

pDC->SetBkMode(TRANSPARENT);
pDC->SetBkColor(TRANSPARENT);
return (HBRUSH)GetStockObject(NULL_BRUSH);

CImage		image;
HRESULT ret = image.Load(strFileName);

image.GetHeight();
pDC->SetStretchBltMode(HALFTONE);
image.Draw(pDC->GetSafeHdc(), 0, 0, rect.right - rect.left, rect.bottom - rect.top);

17.对话框上视图测试

void CPngFile::testView( ){
CDC* pDC;
RECT rect;

pDC = pParentWnd->GetDC();

pParentWnd->GetClientRect(&rect);
rect.bottom = 100;
rect.right = 100;
CRuntimeClass* pViewRuntimeClass = RUNTIME_CLASS(CViewExt);
CView *viewExt = (CViewExt*)pViewRuntimeClass->CreateObject();

//viewExt->Create(NULL, NULL, WS_VISIBLE | WS_CHILD, rect, pParentWnd, 123, NULL);

LONG style = 0;
CStatic* pPictureControl = (CStatic*)pParentWnd->GetDlgItem(IDB_PNG_ControlPanel1);
style = GetWindowLong(pPictureControl->GetSafeHwnd(), GWL_STYLE);
style |= WS_BORDER | SS_GRAYFRAME ;	// SS_BLACKFRAME SS_WHITEFRAME SS_GRAYFRAME

SetWindowLong(pPictureControl->GetSafeHwnd(), GWL_STYLE, style);

pPictureControl->ModifyStyle(SS_WHITEFRAME | WS_BORDER, 0);//去掉边框

}

18.界面控件遍历

HWND hwndChild = ::GetWindow(this->GetSafeHwnd(), GW_CHILD);
while (hwndChild)
{
	CRect rect;		//获取控件大小
	CRectOfControl m_CtrolRect;

	CWnd* pWnd = GetDlgItem(::GetDlgCtrlID(hwndChild));	//获取ID为woc的空间的句柄		
	pWnd->GetWindowRect(&rect);
	ScreenToClient(&rect);		//将控件大小转换为在对话框中的区域坐标
	
	int  nId = ::GetDlgCtrlID(hwndChild);//获得控件的ID;
	hwndChild = ::GetWindow(hwndChild, GW_HWNDNEXT);
}

19.问题
CImageList m_l;
m_l.Create(1,18,TRUE|ILC_COLOR32,1,0);
listCtrl.SetImageList(&m_l,LVSIL_SMALL);
//pDC->FillSolidRect(&rectView, colorSkectchBackGround);
1.类的构造函数带参问题
2.HTREEITEM报错问题
HTREEITEM hParent = NULL;
hParent = m_tree_tools.GetParentItem(m_hTreeItemDrag);
if (!hParent) return ;
www.softWonder.com
3.CList::OnLvnItemchanged事件响应多次的解决方法:
OnLvnItemchangedListServices(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;

if (nIndex >= 7) return;

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if (pNMListView->uChanged != LVIF_STATE)
	return;
if (!(pNMListView->uNewState & LVIS_SELECTED))
return;

}
4.
colorHeaderText = (COLORREF)RGB(0, 0, 0); //(COLORREF)RGB(255,0, 0);
colorBodyText = (COLORREF)RGB(0, 0, 0); //(COLORREF)RGB(0, 0,255);

LOGFONT logFont;
pFontBodyTextNormal = GetFont(); // pDC->GetCurrentFont(); ///  pFont.CreateStockObject(SYSTEM_FONT);

pFontBodyTextNormal->GetLogFont(&logFont);
//logFont.lfEscapement = 0;		//900/10 = 90
logFont.lfHeight = -100;
//logFont.lfWidth = 0;
//logFont.lfOrientation = 0;
//logFont.lfWeight = FW_NORMAL;;

fontBodyTextNormal.DeleteObject() ;

fontBodyTextNormal.CreatePointFontIndirect(&logFont);
CList::OnLvnItemchanged事件响应多次的解决方法:
OnLvnItemchangedListServices(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;

if (nIndex >= 7) return;

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if (pNMListView->uChanged != LVIF_STATE)
	return;
if (!(pNMListView->uNewState & LVIS_SELECTED))
	return;

}
5.CEdit问题:
窗口为模式对话框,失去焦点后,CEdit无法输入数据。为什么?
6.如何隐藏水平滚动条:
// 以下语句只能在:OnPaint()中有效
m_list_services.ShowScrollBar(SB_HORZ, 0);
7. 系统级编译错误:
“CString”与“TCHAR [4]”的间接寻址级别不同

8.MSN关于__try 和 __except例程
struct S1 {
static int smf() { return 0; }
void fnc();
};

void S1::fnc() {
__try {
static int(*array_1[])() = { smf }; // C2712
// OK
static int(*array_2[2])();
array_2[0] = smf;
}
__except (0){
}
}

一、基本知识
1.字符编码问题(字符集 )

//注意:以下n和len的值大小不同,n是按字符计算的,len是按字节计算的
int n = m_EDIT_SectionName.GetLength();
//获取宽字节字符的大小,大小是按字节计算的
int len = WideCharToMultiByte(CP_ACP, 0, m_EDIT_SectionName, m_EDIT_SectionName.GetLength(), NULL, 0, NULL, NULL);
//为多字节字符数组申请空间,数组大小为按字节计算的宽字节字节大小
pSectionName = new char[len + 1];   //以字节为单位
//宽字节编码转换成多字节编码
WideCharToMultiByte(CP_ACP, 0, m_EDIT_SectionName, m_EDIT_SectionName.GetLength(), pSectionName, len, NULL, NULL);
pSectionName[len] = '\0';   //多字节字符以’\0′结束

2.内存问题
以下这个用法是错误的:
char* pFileName = new char[len + 1];
pFileName[len + 1] = ‘\0’; //
delete[] pFileName ;

3.DDX数据更新问题
UpdateData(true),是从控件到变量的提交。
UpdateData(false),是从变量到控件的提交
4.向指定窗口发送消息
pWnd->SendMessage(WM_MOUSEMOVE, 0, MAKELPARAM(point.y, point.y)); //向父窗体发送消息

关于SetCapture() 和 ReleaseCapture()的用法
5.函数如何向外传递字符串?
字符串指针引用,出现内存访问冲突
6.文件操作
判断文件是否结尾:
if (m_fileRead.GetPosition() >= m_fileRead.GetLength()) // 文件结束

文件打开方式:共享方式,追加方式
bool bRet = m_fileWrite.Open(strFileName, CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite | CFile::shareDenyNone); // && m_fileWrite.GetStatus(strFileName, m_fileStatus)

CFile 判断文件句柄是否有效:
if (m_fileWrite.m_hFile == CFile::hFileNull)

CFile 判断文件指针是否到尾部:
while (m_fileExt.m_fileRead.GetPosition() != m_fileExt.m_fileRead.GetLength()){

CFile 移动文件指针:
m_fileWrite.SeekToEnd();

7.消息事件OnMouseLeave, OnMouseMoveTrackMouseEvent和TrackMouseEvent示例

void CStaticExt::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CWnd *pWnd = this->GetParent();

if (pWnd != NULL){
	pWnd->SendMessage(WM_MOUSEMOVE, 0, MAKELPARAM(point.y, point.y));  //向父窗体发送消息
}

if (!m_bOver)
{
	m_bOver = TRUE;

	TRACKMOUSEEVENT tme;
	tme.cbSize = sizeof(TRACKMOUSEEVENT);
	tme.dwFlags = TME_LEAVE;
	tme.hwndTrack = m_hWnd;
	tme.dwHoverTime = 0;
	::TrackMouseEvent(&tme);

	CDC *pCDC = this->GetDC();

	CRect	rect;
	this->GetClientRect(&rect);
	ClientToScreen(&point);

	pCDC->DrawFocusRect(rect);

}
CStatic::OnMouseMove(nFlags, point);

}

void CStaticExt::OnMouseLeave()
{
m_bOver = FALSE;

CDC *pCDC = this->GetDC();

CRect	rect;
this->GetClientRect(&rect);
pCDC->DrawFocusRect(rect);

CStatic::OnMouseLeave();

}

8.获取鼠标光标所在控件的ID

WindowFromPoint和ChildWindowFromPoint函数的使用
HWND WindowFromPoint( POINT Point );

9.获取鼠标光标所在控件的ID
GetCursorPos(&point); //获取当前光标的位置,以便使得菜单可以跟随光标
ScreenToClient(&point); //得到窗体的控件句柄
CWnd* hControlWnd = (CWnd*)ChildWindowFromPoint(point);
10.字符串填充
memset(a,’#’,sizeof(a));
11.对话框上使用CVIEW
// 判断鼠标所在控件
CWnd pWnd = GetFocus();
if(pWnd == NULL)
Return ;
CDC
pDC;
RECT rect;
pDC = pParentWnd->GetDC();
pParentWnd->GetClientRect(&rect);
rect.bottom = 100;
rect.right = 100;
CRuntimeClass* pViewRuntimeClass = RUNTIME_CLASS(CViewExt);
CView viewExt = (CViewExt)pViewRuntimeClass->CreateObject();
viewExt->Create(NULL, NULL, WS_VISIBLE | WS_CHILD, rect, pParentWnd, 123, NULL);

12.字符类型问题
切记:整型和浮点数混合运算时,一定要进行强制类型转换的。严格定义,否则程序运行结果出错
13.IsKindOf(RUNTIME_CLASS(CMFCApplication1Doc)))

CRect rectWndClient;
GetClientRect(&rectWndClient);
CRuntimeClass *pViewRuntimeClass=RUNTIME_CLASS(CMyScrollView);
CMyScrollView pView=(CMyScrollView)pViewRuntimeClass->CreateObject();
View->Create(NULL,NULL,WS_VISIBLE|WS_CHILD, rectWndClient, this,123,NULL);
pView->OnInitialUpdate();

14.修改窗体风格
::GetCurrentDirectory(MAX_PATHLENGTH, des.GetBuffer(MAX_PATHLENGTH));
LONG style = GetWindowLong(pPictureControl->GetSafeHwnd(), GWL_STYLE);

style |= WS_CHILD | SS_BITMAP | SS_CENTERIMAGE;

SetWindowLong(pPictureControl->GetSafeHwnd(), GWL_STYLE, style);

pWnd->ModifyStyle(0, SS_WHITEFRAME | WS_BORDER);//去掉边

15.执行SHELL命令
system( “NOTEPAD.EXE file.txt” );
AfxGetApp()->m_lpCmdLine;
16.控件CStatic显示图片
CStatic* pPictureControl = (CStatic*)GetDlgItem(IDC_STATIC_BMP);
LONG style = GetWindowLong(pPictureControl->GetSafeHwnd(), GWL_STYLE);
style |= WS_CHILD | SS_BITMAP | SS_CENTERIMAGE;
SetWindowLong(pPictureControl->GetSafeHwnd(), GWL_STYLE, style);

CDC* pDC;
pDC = pPictureControl->GetDC();
17.获得命令行参数
AfxGetApp()->m_lpCmdLine;
Settup: Project -> Properties -> Configuration Properties -> Debugging
在Command Arguments里填上即可。
基本知识,API函数:
SetRegistryKey(_T(“Local AppWizard-Generated Applications”));
18.关于构造函数
ProType: CMFCApplication2Dlg(CString strText, CWnd* pParent = NULL); // standard constructor
Define:
CMFCApplication2Dlg::CMFCApplication2Dlg(CString strText, CWnd* pParent )
: CDialogEx(CMFCApplication2Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

stringText = strText;

}
19.获得系统字符集
GetSystemDefaultUILanguage()
对LCID lcid 的值,可以用 WORD PriLan = PRIMARYLANGID(lcid); WORD SubLan = SUBLANGID(lcid);两个方法取得主语言和子语言。如主语言是中文, 那么子语言可以分为中文简体和中文繁体
LCID lcid = GetSystemDefaultLCID();
if(lcid == 0x409)
{
AfxMessageBox(“美国英语”);
}
if(lcid == 0x404)
{
AfxMessageBox(“中国繁体”);//台湾
}
if(lcid == 0x804)
{
AfxMessageBox(“中国简体”); //指中华人民共和国
}

20.CString的实际长度问题
CString szFile;
szFile.GetBuffer(MAX_PATH);

OPENFILENAME ofn;
ofn.lpstrFile = szFile.GetBuffer();
if (GetOpenFileName(&ofn) == NULL)
return ;
如何得到szFile实际长度?
szFile.ReleaseBuffer(); //Must ReleaseBuffer, or GetLength=0

	CString.ReleaseBuffer()要尽量多用,否则会出现意想不到的异常!

21.动态字符串数组的大小
wchar_t *sensors_array[] = { TEXT(“ADCOUNTER\0”), TEXT(“AddCurve\0”), TEXT(“AD\0”), TEXT(“AMI\0”), TEXT(“ATL\0”), TEXT(“AUX\0”), TEXT(“CALCULATE”), TEXT(“COUNTER”), TEXT(“DIGCBL”),
TEXT(“MIDK”), TEXT(“OTHER”), TEXT(“PNN”), TEXT(“RUSPLT”), TEXT(“SBT”), TEXT(“TIMER”), TEXT(“WR”), TEXT(“WSCBUS”), TEXT(“WTC”), TEXT(“YHH”) };

sizeof(sketch_files_array) / sizeof(sketch_files_array[0]);
22.文件选择对话框,文件夹选择对话框,文件保存对话框
CString CToolInsertDlg::SelectDrawingFileName()
{
OPENFILENAME ofn;
CString szFile;

szFile.GetBuffer(MAX_PATH); 	//wchar_t    szFile[MAX_PATH] = { '\0' }, fileExt[4] = { '\0' };		//TCHAR

ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);

ofn.hwndOwner = 0;
ofn.lpstrDefExt = 0;
ofn.lpstrFile = szFile.GetBuffer();
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = TEXT("All File(*.*)\0*.*\0WMF Files(*.wmf)\0*.wmf\0JPG Files(*.jpg)\0*.jpg\0BMP Files(*.bmp)\0");
ofn.nFilterIndex = 0;
ofn.lpstrInitialDir = 0;
ofn.lpstrTitle = 0;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

if (GetOpenFileName(&ofn) == NULL)
	return TEXT("");;

return szFile.GetBuffer();

}

23.格式化字符串
UINT nID = 99 ;
wchar_t buffer_format[128] = { 0 };
swprintf_s(buffer_format, _T(“dFrom%i\0”), nID );

CString strBuffer = _T(“失魂落魄”);
strBuffer.Format();

24.控件和类
Picture Control 就是CStatic
图像类CBitmap
25.控件风格、属性等
CDC* pDC = pEdit->GetDC();
COLORREF clrBack = pDC->GetBkColor();//背景色
COLORREF clrText = pDC->GetTextColor();//文字颜色

HDITEM    curItem;
CHeaderCtrl *listControlHeader = m_listControl_sketch_files.GetHeaderCtrl();
//listControlHeader->ModifyStyle( 0, HDS_BUTTONS ) ;
//listControlHeader->ModifyStyleEx(0, HDS_BUTTONS);

listControlHeader->GetItem(0, &curItem);
curItem.fmt = HDF_CENTER | HDF_STRING;
listControlHeader->SetItem(0, &curItem);

listControlHeader->GetItem(1, &curItem);
curItem.fmt = HDF_CENTER | HDF_STRING;
listControlHeader->SetItem(1, &curItem);

26.调试,对话框
AfxMessageBox(TEXT(“bmp”)); //ofn.lpstrFile
MessageBox(_T(“导入背景图失败!”), _T(“提示”), MB_OK);
DWORD WINAPI GetLastError(void);
TRACE( _T("\n\n这是一个图片") );
TRACE(_T("\n\n这是一个图片%i "), 3);
27.关于文件夹、目录
CString strFile, strAppPath ;

strFile.GetBuffer(MAX_PATH);
GetCurrentDirectory(MAX_PATH, strFile.GetBuffer());
strFile.ReleaseBuffer();		//Must ReleaseBuffer, or GetLength=0
AfxMessageBox(strFile);

GetModuleFileName(NULL, strAppPath.GetBuffer(MAX_PATH), MAX_PATH); //.GetBuffer(MAX_PATH)
strAppPath.ReleaseBuffer();		//Must ReleaseBuffer, or GetLength=0
int len = strAppPath.GetLength();
int pos = strAppPath.ReverseFind(_T('\\'));
//strFile = strAppPath.Left(len - pos + 3);
strFile = strAppPath.Right(len - pos - 1);
AfxMessageBox( strFile );

	::GetCurrentDirectory(MAX_PATHLENGTH, des.GetBuffer(MAX_PATHLENGTH));
	GetPrivateProfileString(TEXT("ExeFilePath"), arrayObjecsCommand[-arrayItemsLength[n + 1]], TEXT("TestApplication.exe"), SName.GetBuffer(MAX_PATHLENGTH), MAX_PATHLENGTH, des);

	ShellExecute(NULL, TEXT("open"), TEXT("TestApplication.exe"), arrayObjecsCommand[-arrayItemsLength[n + 1]], NULL, 0);

28.字符串操作
CharLower
29.原子操作
AddAtom、DeleteAtom、FindAtom、GetAtomName、GlobalAddAtom、
GlobalDeleteAtom、GlobalFindAtom、GlobalGetAtomName
30.内存操作
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
GlobalUnlock(hGlobal);
GlobalAlloc,GlobalLock,GlobalUnLock
HeapAlloc, LocalAlloc, New, Malloc

OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
31.窗口操作
AfxGetInstanceHandle();
this->GetSafeHwnd();
GetParentFrame ( ) ;
32.关于系统消息和系统虚函数
注意public和protected:
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
public:
virtual void OnDraw(CDC* pDC); // 重写以绘制该视图
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
33.系统相关API等
KillTimer(hWnd, 0);
CloseWindow( hWnd );
exitinstance();
exit( 0 );

DWORD dwProcessId = 0;
DWORD dwThreadID = GetWindowThreadProcessId(hWnd, &dwProcessId) ;
long intance = GetWindowLong(hWnd, GWL_HINSTANCE );

TerminateProcess(&dwProcessId, 0);
TerminateProcess(&dwThreadID, 0 );

// 以下三种均可正常关闭窗口
PostQuitMessage(0);
SendMessage(hWnd, WM_CLOSE, 0, 0);
DestroyWindow( hWnd );

GetDocument() ;
34.显示WMF图元文件
HENHMETAFILE hemf = GetEnhMetaFile(ofn.lpstrFile) ;
CDC * pDC = GetDC();
PlayEnhMetaFile(pDC->m_hDC, hemf, &rect);
DeleteEnhMetaFile( hemf );
///以下为基本内容/
CMetalFile
HENHMETAFILE GetEnhMetaFile( LPCTSTR lpszMetaFile // file name );
BOOL PlayEnhMetaFile( HDC hdc, // handle to DC HENHMETAFILE hemf, // handle to an enhanced metafile CONST RECT *lpRect // bounding rectangle );
35.程序异常捕获,稳健性,抛出异常
GetLastError()
TRACE(_T("\n\n这是一个图片%i "), 3);
ASSERT( TRUE );
VERIFY(TRUE);
throw 0;

__try {

}
__except (EXCEPTION_EXECUTE_HANDLER){

}
36.通用ICO图片显示
基本知识:
HICON m_hIcon;
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

SetIcon(m_hIcon, TRUE);			// Set big icon
dc.DrawIcon(x, y, m_hIcon);

void CPngFile::readIcoFile(CWnd* pPictureControl, CString strFileName){
CDC* pDC;
RECT rect;

if (!PathFileExists(strFileName))
	return;

pDC = pPictureControl->GetDC();
pPictureControl->GetClientRect(&rect);

showPitcture_BmpJpgGifWmf(pDC, strFileName, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);

}

37.通用png图片显示
void CPngFile::readPngFile(CWnd* pPictureControl, CString strFileName){
// filename 是要加载的文件名
CDC* pDC;
RECT rect;
CImage image;

if (!PathFileExists(strFileName))
	return;

pDC = pPictureControl->GetDC();
pPictureControl->GetClientRect(&rect);

//image.LoadFromResource
HRESULT ret = image.Load(strFileName);

pPictureControl->GetWindowRect(&rect);
//pPictureControl->SetWindowPos(NULL, 0, 0, rect.right, rect.top + 100, SWP_NOZORDER | SWP_NOMOVE);  ///rect.bottom

//AfxMessageBox( strFileName );
if (image.IsNull()) {
	AfxMessageBox(_T("没有加载成功"));
	return;
}

if (image.GetBPP() == 32)	//确认该图像包含Alpha通道 
{
	int i;
	int j;
	for (i = 0; i < image.GetWidth(); i++)
	{
		for (j = 0; j < image.GetHeight(); j++)
		{
			byte *pByte = (byte *)image.GetPixelAddress(i, j);
			pByte[0] = pByte[0] * pByte[3] / 255;
			pByte[1] = pByte[1] * pByte[3] / 255;
			pByte[2] = pByte[2] * pByte[3] / 255;
		}
	}
}
image.Draw(pDC->m_hDC, 0, 0);
//image.Draw(pDC->GetSafeHdc(), 0, 0, rect.right - rect.left, rect.bottom - rect.top);

}

38.通用图片显示:bmp, jpg, gif, wmf,不支持png
void CPngFile::DarwPic(CDC* pDC, int nID_Resource, CRect rc)
{
// = this->GetClientRect(&rc);

CBitmap cbmp;
CDC dcImage;

// IDB_PNG_ControlPanel1
cbmp.LoadBitmap( nID_Resource );
CSize size = cbmp.GetBitmapDimension();

dcImage.CreateCompatibleDC(pDC);
dcImage.SelectObject(&cbmp);

pDC->StretchBlt(0, 0, size.cx, size.cy, &dcImage, 0, 0, rc.Width(), rc.Height(), SRCCOPY);

}

void CPngFile::openPngFile(CDC* pDC, CString strFileName, RECT rect){
// filename 是要加载的文件名(包含路径)
CImage image ;

if (!PathFileExists(strFileName))
	return ;

HRESULT		ret = image.Load( strFileName );
if (!ret)
	return;

HBITMAP		hBitMap = image.Detach();
CBitmap		mBitmap;

mBitmap.Attach( hBitMap );		//	由HBITMAP 得到关联的CBitmap 

int		srcWidth = image.GetWidth() ;
int		srcHeight = image.GetHeight() ;

HDC		hdc = pDC->m_hDC;
image.Draw(hdc, rect);

//BITMAP		bitmap;
//GetObject(hBitMap, sizeof(BITMAP), (LPBYTE)&bitmap);
//image.Draw(hdc, &rect);
//bitmap.GetBitmap(&bm);		//	由CBitmap 得到关联的BITMAP
//hBitmap=(HBITMAP)bitmap.GetSafeHandle();//由CBitmap得到相关的HBITMAP

}

CBitmap 类只能处理BMP格式的图片,非常受限。
而CImage可以处理JPGE GIF BMP PNG多种格式图片,扩展了图片处理功能 且能与CBitmap 进行转换( 因为所载入的位图句柄都是HBITMAP,所以可相互转换),因此引入CImage类进行图像处理

// 根据图片文件的名称, 在指定位置显示图片

bool CToolInsertDlg::showGraph_JpgGifBmpWmf(CDC* pDC, CString strPath, int x, int y, int width, int height, COLORREF colorBack)
{
CFile file;
CFileStatus fstatus;
IStream *pStm;

LONG		cb;
HGLOBAL		hGlobal = NULL;
LPVOID		pvData = NULL;

// 打开文件
if (!(file.Open(strPath, CFile::modeRead) && file.GetStatus(strPath, fstatus) && ((cb = fstatus.m_size) != -1))) {
	return false;
}

// 分配内存
hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
if (!hGlobal)
{
	file.Close();
	return false;
}

// 锁定内存
pvData = GlobalLock(hGlobal);
if (!pvData)
{
	file.Close();
	GlobalFree(hGlobal);
	return false;
}

//读取文件
file.Read(pvData, cb);
file.Close();

GlobalUnlock(hGlobal);
CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);

//显示JPEG和GIF格式的图片,GIF只能显示一帧,还不能显示动画,
//要显示动画GIF请使用ACTIVE控//件。
IPicture *pPic = nullptr;

/// load image from file stream
if (!SUCCEEDED(OleLoadPicture(pStm, fstatus.m_size, TRUE, IID_IPicture, (LPVOID*)&pPic)))
{
	GlobalFree(hGlobal);
	return false;
}
GlobalFree(hGlobal);

RECT rect;
rect.left = x; rect.top = y; rect.bottom = y + height; rect.right = x + width;
// 因为前后图片大小不一,故清除区域
pDC->FillSolidRect(&rect, colorBack);

OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;

//get image height and width
pPic->get_Width(&hmWidth);
pPic->get_Height(&hmHeight);

double fX, fY;

fX = (double)pDC->GetDeviceCaps(HORZRES)*(double)hmWidth / ((double)pDC->GetDeviceCaps(HORZSIZE)*100.0);
fY = (double)pDC->GetDeviceCaps(VERTRES)*(double)hmHeight / ((double)pDC->GetDeviceCaps(VERTSIZE)*100.0);
if (fX - x > width)
	fX = x + width;
if (fY - y > height)
	fY = y + height;

//use render function display image
if (FAILED(pPic->Render(*pDC, x, y, (DWORD)fX, (DWORD)fY, 0, hmHeight, hmWidth, -hmHeight, NULL)))
{
	pPic->Release();
	return false;
}
pPic->Release();

return true;

}
39.其它
m_crText = GetSysColor(COLOR_WINDOWTEXT);
m_crBackGnd = GetSysColor(COLOR_WINDOW);
CRectTracker
pDC->ExtTextOut 实现文字旋转

二、在设备上动态显示图片CDC, CBitmap, BITMAP, HBITMAP, WMF, ICO
上面是CDC?试看下例:
CDC * pDC = m_list_used_sensors.GetDC();

void CMFCViewTestView::OnDraw(CDC* pDC)
{
BITMAP mBITMAP;
CBitmap mBitmap;

CFont *pfontOld = pDC->GetCurrentFont();//保存原始

HBITMAP	hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(), _T("res//PH02740U.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
mBitmap.DeleteObject();
if (!mBitmap.Attach( hBitmap ))
{
	MessageBox(_T("导入背景图失败!"), _T("提示"), MB_OK);
	return;
}
mBitmap.GetObject( sizeof(BITMAP), &mBITMAP );

CDC		compDC;

compDC.CreateCompatibleDC(pDC);
compDC.SelectObject(&mBitmap);
pDC->BitBlt(100, 20, mBITMAP.bmWidth, mBITMAP.bmHeight, &compDC, 0, 0, SRCCOPY);
compDC.DeleteDC();

pDC->SelectObject(pfontOld);
}

三、 屏幕坐标和用户区坐标
举例:
// m_static.GetClientRect(&rect);
m_static.GetWindowRect(&rect);
ScreenToClient(&rect);
//MoveWindow(rect);
m_static.SetWindowPos(m_static.GetParent(), rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);

void CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nTimerid, DWORD dwTime)
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
}

//m_static.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOSIZE);

四、 资源
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
五、 在设备上输出透明色文字,文字宽度
/// 文字宽度
point = pDC->GetTextExtent(strText);


CDC* pDC ;
CFont font ;

CFont *pfontOld = pDC->GetCurrentFont();//保存原始

font.CreateFont(
	80, 0, 700, 0, FW_BOLD, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
	DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("Arial"));  // FW_NORMAL

pDC->SelectObject(&font);
pDC->SetBkMode(TRANSPARENT);

pDC->SetTextColor(RGB(255, 20, 60)); //设置字体颜色
pDC->TextOut(600, 300, _T("横七竖八"));

pDC->SelectObject(pfontOld); // 恢复

六、控件提示信息框 - CToolTipCtrl,控件需设置SS_NOTIFY属性
控件属性: SS_NOTIFY // Notify = True ;
在h文件中:
protected:
CToolTipCtrl m_pToolTipCtrl;
public:
afx_msg BOOL OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult);
在cpp文件中:
BEGIN_MESSAGE_MAP(CMenuTestDlg, CDialogEx)
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipNotify)
END_MESSAGE_MAP()

BOOL CMenuTestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();

m_pToolTipCtrl.AddTool(GetDlgItem(IDC_BITMAP1), LPSTR_TEXTCALLBACK);
EnableToolTips(TRUE);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}

int CMenuTestDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;

if (!m_pToolTipCtrl.Create(this)) return FALSE;
// TODO:  在此添加您专用的创建代码

return 0;

}

BOOL CMenuTestDlg::OnToolTipNotify(UINT id, NMHDR * pTTTStruct, LRESULT * pResult)
{
UNREFERENCED_PARAMETER(id);
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pTTTStruct;

UINT nID = pTTTStruct->idFrom ;

if (pTTT->uFlags && TTF_IDISHWND)
{
	nID = ::GetDlgCtrlID((HWND)nID);

	switch (nID)
	{
	case IDC_BITMAP1:
		pTTT->lpszText =  _T("这是一个图片控件Picture Control");
		pTTT->hinst = AfxGetResourceHandle();
		break;
	case IDC_STATIC2:
		pTTT->lpszText = _T("这是一个静态文本控件Static Text");
		pTTT->hinst = AfxGetResourceHandle();
		break;
	case IDC_LIST1:
		pTTT->lpszText = _T("这是一个列表框控件Static Text");
		pTTT->hinst = AfxGetResourceHandle();
		break;
	}
}
*pResult = 0;
return TRUE;

}
七、鼠标事件
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
八、MFC架构
void CMenuTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_STATIC1, m_static);
}

BEGIN_MESSAGE_MAP(CMenuTestDlg, CDialogEx)
ON_WM_PAINT()
ON_COMMAND(ID_InsertMenuItem, &CMenuTestDlg::OnInsertmenuitem)
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
九、List Control的用法
1.CList::OnLvnItemchanged事件响应多次的解决方法:
OnLvnItemchangedListServices(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;

if (nIndex >= 7) return;

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if (pNMListView->uChanged != LVIF_STATE)
	return;
if (!(pNMListView->uNewState & LVIS_SELECTED))
return;

}
注意:在VS2015中,必须加以下语句,否则控件disable:
long dwStyle = m_list_services.GetExtendedStyle();

dwStyle |= LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT;		//网格线(只适用与报表风格的listctrl)LVS_EX_CHECKBOXES
																									//m_list_services.ModifyStyle(0, LVS_REPORT);  //LVS_REPORT  LVS_LIST
m_list_services.SetExtendedStyle(dwStyle);
m_list_services.ShowScrollBar(SB_HORZ, 0);
m_list_services.SetRedraw();	

/

// Itemchanged 事件的响应
void Clist::OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR);

NMLISTVIEW *pNMListView = (NMLISTVIEW*)pNMHDR;
if (-1 != pNMListView->iItem)	// 如果iItem不是-1,就说明有列表项被选择   
	CName = m_programList.GetItemText(pNMListView->iItem, 0);

}
/ 得到选中行
int row = m_listControl_sketch_files.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);
//int row = m_listControl_sketch_files.GetSelectedColumn();

// List Control的高亮显示问题 //
listCtrlSource->SetSelectedColumn(rowSource);
listCtrlSource->SetItemState(rowSource, LVIS_SELECTED, LVIS_SELECTED); //高亮
listCtrlSource->SetFocus();
listCtrlSource->SetRedraw();
//m_list_all_sensors.EnsureVisible(rowTarget, FALSE);
//m_list_all_sensors.SetCheck(rowTarget, TRUE);
// //

long dwStyle = m_list_all_sensors.GetExtendedStyle();

dwStyle |= LVS_EX_GRIDLINES;		//网格线(只适用与报表风格的listctrl)LVS_EX_CHECKBOXES
dwStyle |= LVS_EX_FULLROWSELECT;

m_list_all_sensors.ModifyStyle(0, LVS_REPORT);  //LVS_REPORT  LVS_LIST
m_list_all_sensors.SetExtendedStyle(dwStyle);

CRect lc_rect;
m_list_all_sensors.GetWindowRect(&lc_rect);
DWORD dwListLength = lc_rect.Width() / 3;

m_list_all_sensors.InsertColumn(0, _T("Name"), LVCFMT_LEFT | LVCFMT_IMAGE, dwListLength); // LVCFMT_LEFT
m_list_all_sensors.InsertColumn(1, _T("PathName"), LVCFMT_LEFT, dwListLength);
m_list_all_sensors.InsertColumn(2, _T("Create"), LVCFMT_LEFT, dwListLength );

int row = m_list_all_sensors.InsertItem(0,  _T("什么是Label") );		//设置第0行,第1列值
m_list_all_sensors.SetItemText(row, 0,  _T("什么是Label") );		//设置第0行,第1列值
m_list_all_sensors.SetItemText(row, 1,  _T("什么是Label") );		//设置第0行,第1列值

十、动态生成 - 图片,静态文字,按钮
有的控件不能在对话框上显示

#define ID_BUTTON1 1100
#define ID_STATIC1 1101
#define ID_STATIC2 1102

CButton m_button;
CBitmap m_bitmap ;

CStatic m_static;
CStatic m_picture;

int CMFCViewTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;

m_button.Create(_T("按钮"), WS_CHILD | WS_VISIBLE, CRect(10, 10, 100, 50), this, ID_BUTTON1);
	
m_static.Create(_T("这是静态文本:西安威盛公司"), SS_LEFT | WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | SS_NOTIFY, CRect(10, 300, 600, 350), this, ID_STATIC1);;
m_picture.Create(_T(""), SS_BITMAP | WS_VISIBLE  | SS_NOTIFY, CRect(330, 20, 500, 200), this, ID_STATIC2);;

HBITMAP mHBITMAP;
mHBITMAP = (HBITMAP)LoadImage(AfxGetInstanceHandle(), _T("res//NiceWorld.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
m_picture.SetBitmap( mHBITMAP );

return 0;

}
十一、窗口消息OnCtlColor: 设置透明色(更改颜色)
// 窗口颜色更改
HBRUSH CMFCViewTestView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CView::OnCtlColor(pDC, pWnd, nCtlColor);

if (pWnd == GetDlgItem(ID_STATIC1)){
	CFont font ;
	font.CreateFont(
		36, 0, 0, 0, FW_BOLD, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
		DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("宋体"));


	pDC->SelectObject(&font);
	pDC->SetTextColor(RGB(0, 0, 255));
    pDC->SetBkMode(TRANSPARENT);
	pDC->SetBkColor( TRANSPARENT );	// OPAQUE
	
	//hbr = ::CreateSolidBrush( TRANSPARENT );
	//hbr = CreateSolidBrush(OPAQUE);
	return (HBRUSH)GetStockObject(NULL_BRUSH);
}

return hbr;

十二、定时器
//SetTimer((UINT)m_hWnd, (UINT)5555, TimerProc); // 触发定时器程序TimerProc工作
SetTimer((UINT)m_hWnd, (UINT)60, NULL); // 启动窗口hWnd的定时器

void CDlgCtrlTest::OnTimer(UINT_PTR nIDEvent){
CRect rect;

GetClientRect(&rect); 	
m_static.GetWindowRect(&rect);
ScreenToClient(&rect);

//MoveWindow(rect);
m_static.SetWindowPos(m_static.GetParent(), rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
m_static.RedrawWindow( );

CDialogEx::OnTimer(nIDEvent);
}
十三、消息

十四、字体 - 设置和更改控件字体
// 设置CStatic Control控件
CFont * cFont = new CFont;

cFont->CreateFont(48, 0, 600, 90, FW_BOLD, FALSE, FALSE, 0,
	ANSI_CHARSET, OUT_DEFAULT_PRECIS,
	CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
	DEFAULT_PITCH&FF_SWISS, _T("Arial"));

//cFont->CreatePointFont(4, _T("楷体"));
GetDlgItem(IDC_STATIC1)->SetFont(cFont);

// 更改字体
///
注意:前面必须已经创建对象pDC->SelectObject(&font),否则报错
CFont* pFont = pDC->GetCurrentFont();

LOGFONT logFont;
pFont->GetLogFont(&logFont);
logFont.lfEscapement = 900;//900/10 = 90
logFont.lfHeight = 80;
logFont.lfWidth =32;
logFont.lfWeight = 11;

pFont->DeleteObject();
pFont->CreateFontIndirect(&logFont);
pDC->SelectObject( pFont );

/// 以下效果不好 ///
CFont font2 ;
font2.CreateStockObject( SYSTEM_FONT );

LOGFONT logFont;
font2.GetLogFont(&logFont);
logFont.lfEscapement = 900;//900/10 = 90
logFont.lfHeight = 80;
logFont.lfWidth =32;
logFont.lfWeight = 11;

font2.DeleteObject();
font2.CreateFontIndirect(&logFont);
pDC->SelectObject( font2 );

十五、 Animation Control控件
if (m_animate.Open(_T(“res\correct.avi”)))
{
m_animate.Play(0, (UINT)-1, (UINT)-1);// 从头播放到尾
}
十六、图片
1.
十七、DLL动态链接库
1.
十八、文件操作
1.if (!PathFileExists(strFileName))
return;
十九、菜单CMenu
1.动态生成菜单
2.删除菜单命令
3.删除部分菜单
4.增加菜单命令
5.替换整个菜单
6.菜单响应(单击)
7.右键快捷菜单

BEGIN_MESSAGE_MAP(CMenuTestDlg, CDialogEx)
ON_COMMAND(ID_InsertMenuItem, &CMenuTestDlg::OnInsertmenuitem)
ON_COMMAND(ID_DeleteMenuItem, &CMenuTestDlg::OnDeletemenuitem)
ON_COMMAND(ID_DeleteMenu, &CMenuTestDlg::OnDeletemenu)
ON_COMMAND(ID_MenuReplace, &CMenuTestDlg::OnMenureplace)
ON_WM_RBUTTONDOWN()
END_MESSAGE_MAP()

BOOL CMenuTestDlg::OnInitDialog(){
BOOL CMenuTestDlg::OnInitDialog()
// 将“关于…”菜单项添加到系统菜单中。

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
	BOOL bNameValid;
	CString strAboutMenu;
	bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
	ASSERT(bNameValid);
	if (!strAboutMenu.IsEmpty())
	{
		pSysMenu->AppendMenu(MF_SEPARATOR);
		pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
	}
}

m_Menu.LoadMenu(IDR_MENU_TEST); // IDR_MENU1
SetMenu(&m_Menu); // TODO: 在此添加额外的初始化

return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}

void CMenuTestDlg::OnInsertmenuitem()
{
MENUITEMINFO mInfo;

wchar_t buffer_format[128] = { 0 };
swprintf_s(buffer_format, _T("动态菜单命令%i\0"), ID_MENUID_START);

mInfo.cbSize = sizeof(MENUITEMINFO);
mInfo.dwTypeData = buffer_format;
mInfo.fType = MFT_STRING;
mInfo.wID = ID_MENUID_START;
ID_MENUID_START = ID_MENUID_START + 1;
mInfo.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID;

// 在当前菜单命令位置前增加新菜单命令
AfxGetMainWnd()->GetMenu()->InsertMenuItemW(ID_InsertMenuItem, &mInfo, FALSE);

AfxGetMainWnd()->DrawMenuBar();	//绘制菜单
AfxGetMainWnd()->GetMenu()->Detach();

}

void CMenuTestDlg::OnDeletemenuitem()
{
CString strName;
CMenu *pMenu = AfxGetMainWnd()->GetMenu();

//MF_BYPOSITION或MF_BYCOMMAND
pMenu->GetMenuString(ID_DeleteMenuItem, strName, MF_BYCOMMAND);

HWND m_hWnd = GetSafeHwnd();
HMENU hMenu = ::GetMenu(m_hWnd);
DeleteMenu(hMenu, ID_DeleteMenuItem, MF_BYCOMMAND);

MessageBox(strName);

}

void CMenuTestDlg::OnDeletemenu()
{
// TODO: 在此添加命令处理程序代码
HWND m_hWnd = GetSafeHwnd();

// 删除自身菜单命令
HMENU hMenu = ::GetMenu(m_hWnd);
DeleteMenu(hMenu, 0, MF_BYPOSITION);
AfxGetMainWnd()->DrawMenuBar();//绘制菜单
}

void CMenuTestDlg::OnMenureplace()
{
CMenu menu; //定义菜单对象
menu.LoadMenuW( IDR_MAINFRAME1 );//加载信息菜单
AfxGetMainWnd()->SetMenu(&menu);//设置菜单
AfxGetMainWnd()->DrawMenuBar();//绘制菜单

menu.Detach();//  
TRACE0("/n/nID_EDIT_UNDO/n");

}

BOOL CMenuTestDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
wchar_t buffer_format[128] = { 0 };

UINT uMsg = LOWORD(wParam);
if (uMsg >= ID_MENUID_FIRST && uMsg <= ID_MENUID_FIRST + 100)
{
	swprintf_s(buffer_format, _T("动态菜单命令%i\0"), uMsg);
	MessageBox(buffer_format);
}

return CDialogEx::OnCommand(wParam, lParam);

}

工作区(用户区)右键菜单:
void CMenuTestDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
CMenu menu;

menu.LoadMenu(IDR_POPUP_EDIT );
CMenu* pPopUp = menu.GetSubMenu(0);//获取菜单的第一个子菜单,序号为0
ClientToScreen( &point );//坐标转换
pPopUp->TrackPopupMenu  (TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y, this);

CDialogEx::OnLButtonDown(nFlags, point);

}

控件右键快捷菜单:
BOOL CMenuTestDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// 控件右键快捷菜单
CPoint point;
CMenu menu;

//HWND hHnd = GetDlgItem(IDB_BITMAP1)->GetSafeHwnd();
//if (pWnd  == GetDlgItem(IDB_BITMAP1))		// 有问题,需调试
if (message == WM_RBUTTONDOWN)
{
	menu.LoadMenu(IDR_POPUP_EDIT);
	GetCursorPos(&point);
	//ClientToScreen(&point);//坐标转换
	CMenu* pPopUp = menu.GetSubMenu(0);//获取菜单的第一个子菜单,序号为0
	pPopUp->TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y, this);
}

return CDialogEx::OnSetCursor(pWnd, nHitTest, message);

}

二十、实例,句柄HWND,窗口类CWnd, 对象
CWnd的成员: m_pMainWnd
获取窗口句柄
获取自身窗口句柄
HWND hWnd = AfxGetMainWnd()->m_hWnd ;
CWnd* pParentWnd = FromHandle(this->GetSafeHwnd());
CWnd* pParentWnd = this->GetSafeOwner();

 罗列窗体上所有控件
HWND hwndChild = ::GetWindow(m_hWnd, GW_CHILD); //列出所有控件

while (hwndChild){
int nID = ::GetDlgCtrlID(hwndChild); //获得控件的ID
CWnd *pWnd = GetDlgItem(nID); //获取ID为woc的空间的句柄
hwndChild = ::GetWindow(hwndChild, GW_HWNDNEXT);
}
 获取父窗口Z序顶部的子窗口句柄
HWND GetTopWindow(HWND hWnd) ;
如果hWnd为NULL,返回Z序顶部的窗口句柄。如果指定的窗口无子窗口,返回值为NULL。
获取系统的前台窗口句柄
HWND GeCWnd *pwndtForegroundWindow(VOID) ;
获取当前进程的活动窗口句柄
HWND GetActiveWindow(VOID) ;
获取当前进程的活动窗口句柄
FindWindow(“ExploreWClass”,NULL); //希望找到资源管理器
  HWND hwnd = pwnd->GetSafeHwnd(); //得到它的HWND
HWND hwnd = pwnd->m_hwnd; //得到它的HWND,不建议用
判断窗口句柄是否存在窗口
BOOL IsWindow(HWND hWnd);
判断窗口句柄是否存在窗口
HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName );
BOOL SetWindowTextW( HWND hWnd, LPCWSTR lpString );
改变窗口标题
BOOL SetWindowTextW( HWND hWnd, LPCWSTR lpString );
GetDigitem (IDC_BUTTON) -> SetWindowText (_T ("Button new title ") );
判断窗口句柄是否存在窗口
HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName );
判断窗口句柄是否存在窗口
HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName );
二十一、临时-待处理
HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName );
二十二、其它
H
lpWindowName );
二十三、图像问题
原理方法
显示资源中的图片
(1)从资源中装入位图
● 定义位图对象数据成员CBitmap m_Bitmap;
● 调用CBitmap成员函数LoadBitmap(),如m_Bitmap.LoadBitmap(IDB_BITMAP1);
● 传入LoadBitmap的参数是位图在图形编辑器中生成或从位图文件中引入时赋予的识别符。
(2)生成与位图相联系的内存设备情境对象
CDC MemDC;
MemDC.CreateCompatibleDC(NULL);
MemDC.SelectObject(&m_Bitmap);
(3)显示位图
CClientDC ClientDC(this);
BITMAP BM;
m_Bitmap.GetObject(sizeof(BM),&BM);
ClientDC.BitBlt ( X,Y, //目标设备逻辑横、纵坐标
BM.bmWidth, BM.bmHeight, //显示位图的像素宽、高度
&MemDC, //待显示位图数据的设备情境对象
0,0, //源数据中的横、纵坐标
SRCCOPY); //位操作方式
特点:这种方法显示位图速度快,但不是很灵活,而且会使可执行文件增大。

显示磁盘中的图片
步骤:
HBITMAP hBitmap; //定义位图对象句柄
BITMAP BM;
CDC MemDC;
CClientDC ClientDC(this);
MemDC.CreateCompatibleDC(&ClientDC);
hBitmap=(HBITMAP
):: LoadImage ( AfxGetInstanceHandle(), //取得应用程序句柄
“demo1.bmp”, //位图文件名
IMAGE_BITMAP, //类型为Windows位图
0,0, LR_LOADFROMFILE); //从文件中取位图数据
MemDC.SelectObject(hBitmap);
:: GetObject(hBitmap,sizeof(BM),&BM);
ClientDC.BitBlt(……) //使用格式与方法一同
特点:这种方法显示位图速度较之前一种慢了一点,但其灵活性较大,可以任意变换位图文件,而无需重新编译源程序, 也减小了可执行文件的大小。

程序模板
显示资源中的图片/在设备上下文中绘制图像[1]
法一
void COutputBmpView::OnDraw(CDC* pDC)
{
COutputBmpDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CDC memDC;//定义一个设备上下文
memDC.CreateCompatibleDC(pDC);//获取兼容的设备上下文
CBitmap bmp;
bmp.LoadBitmap(IDB_BKBITMAP);
memDC.SelectObject(&bmp);//选中位图对象
pDC->BitBlt(30,20,180,180,&memDC,1,1,SRCCOPY);//绘制位图
CRect rc(30,20,210,200);
CBrush brush(RGB(0,0,0));
pDC->FrameRect(rc,&brush);//绘制矩形边框
rc.OffsetRect(220,0);//移动区域
BITMAP BitInfo;
bmp.GetBitmap(&BitInfo);
int x = BitInfo.bmWidth;
int y = BitInfo.bmHeight;
pDC->StretchBlt(rc.left,rc.top,rc.Width(),rc.Height(),&memDC,0,0,x,y,SRCCOPY);//绘制位图
pDC->FrameRect(rc,&brush);
brush.DeleteObject();
memDC.DeleteDC();//释放设备上下文
bmp.DeleteObject();//释放文图对象
}

在磁盘中加载图像到窗口中[1]
CLoadBmpView::CLoadBmpView()//构造函数中
{
m_hBmp = LoadImage(NULL,“Demo.bmp”,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);//加载位图
}
void CLoadBmpView::OnDraw(CDC* pDC)
{
CLoadBmpDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CBitmap bmp;
bmp.Attach(m_hBmp);//将位图关联到位图句柄上
CDC memDC;
memDC.CreateCompatibleDC(pDC);//创建兼容的设备上下文
memDC.SelectObject(&bmp);//选中位图对象
BITMAP BitInfo; //定义位图结构
bmp.GetBitmap(&BitInfo); //获取位图信息
int x = BitInfo.bmWidth; //获取位图宽度
int y = BitInfo.bmHeight; //获取位图高度
pDC->BitBlt(0,0,x,y,&memDC,0,0,SRCCOPY);//向窗口中绘制位图
bmp.Detach();//分离位图句柄
memDC.DeleteDC();//释放设备上下文
}
根据位图数据直接绘图[1]
char *m_pBmpData;//①在视图类中定义一个缓冲区
COutputStreamView::COutputStreamView()//②构造函数中读取文件到数据流中
{
CFile file;//定义文件对象
file.Open(“bk.bmp”,CFile::modeReadWrite);
int len = file.GetLength();
file.Seek(14,CFile::begin); //*过位图文件头
m_pBmpData = new char[len-14];//为缓冲区分配空间
file.Read(m_pBmpData,len-14);//读取文件数据到缓冲区
file.Close();
}
COutputStreamView::~COutputStreamView()//③析构函数中释放缓冲区
{
delete [] m_pBmpData;
}
void COutputStreamView::OutputStream(char pStream)//④添加的成员函数,用来根据数据流输出图像
{
char pHeader =pStream ;//定义临时缓冲区
BITMAPINFO BitInfo;
memset(&BitInfo,0,sizeof(BITMAPINFO));//初始化位图信息对象
memcpy(&BitInfo,pHeader,sizeof(BITMAPINFO));//为位图信息对象赋值
int x = BitInfo.bmiHeader.biWidth;
int y = BitInfo.bmiHeader.biHeight;
pHeader+=40;//指向位图数据
StretchDIBits(GetDC()->m_hDC,0,0,x,y,0,0,x,y,pHeader,&BitInfo,DIB_RGB_COLORS,SRCCOPY);
}
void COutputStreamView::OnDraw(CDC
pDC)//⑥绘制图像
{
COutputStreamDoc
pDoc = GetDocument();
ASSERT_VALID(pDoc);
OutputStream(m_pBmpData);//输出位图
}

显示JPEG图像[1]
①向视图类添加成员变量
IStream m_pStream; //定义流对象
IPicture m_pPicture; //定义接口对象
OLE_XSIZE_HIMETRIC m_JPGWidth; //图像宽度
OLE_YSIZE_HIMETRIC m_JPGHeight; //图像高度
HGLOBAL hMem; //堆句柄
CShowJPEGView::CShowJPEGView()//②构造函数:从磁盘中加载IPEG位图到流中
{
CFile file;
file.Open(“angell.jpg”,CFile::modeReadWrite);
DWORD len = file.GetLength();
hMem = GlobalAlloc(GMEM_MOVEABLE,len);//在堆中分配内存
LPVOID pData = NULL; //定义一个指针对象
pData = GlobalLock(hMem);//锁定内存区域
file.ReadHuge(pData,len);//读取图像数据到堆中
file.Close();//
GlobalUnlock(hMem);//解除对堆得锁定
CreateStreamOnHGlobal(hMem,TRUE,&m_pStream);//在堆中创建流
OleLoadPicture(m_pStream,len,TRUE,IID_IPicture,(LPVOID
)&m_pPicture);//加载图像
m_pPicture->get_Height(&m_JPGHeight);//获取图像高度
m_pPicture->get_Width(&m_JPGWidth);
}
void CShowJPEGView::OnDraw(CDC
pDC)//③绘制JPEG图像
{
CShowJPEGDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
m_pPicture->Render(pDC->m_hDC,0,0,(int)(m_JPGWidth/26.45),(int)(m_JPGHeight/26.45)
,0,m_JPGHeight,m_JPGWidth,-m_JPGHeight,NULL); //绘制JPEG图像
}

HBITMAP CMFCAppMenuDlg::CopyScreenToBitmap(LPRECT lpRect) {
HDC hScrDC, hMemDC; // 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap; // 位图句柄
int nX, nY, nX2, nY2; // 选定区域坐标
int nWidth, nHeight; // 位图宽度和高度
int xScrn, yScrn; // 屏幕分辨率 // 确保选定区域不为空矩形
if (IsRectEmpty(lpRect))
return NULL; //为屏幕创建设备描述表
hScrDC = CreateDC(TEXT(“DISPLAY”), NULL, NULL, NULL); //为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC); // 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom; // 获得屏幕分辨率
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES); //确保选定区域是可见的
if (nX < 0)
nX = 0;

if (nY < 0)
	nY = 0;
if (nX2 > xScrn)
	nX2 = xScrn;
if (nY2 > yScrn)
	
nY2 = yScrn;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 创建一个与屏幕设备描述表兼容的位图    hBitmap=CreateCompatibleBitmap(hScrDC,nWidth,nHeight);    // 把新位图选到内存设备描述表中     hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);    // 把屏幕设备描述表拷贝到内存设备描述表中     BitBlt(hMemDC,0,0, nWidth,nHeight,hScrDC, nX, nY, SRCCOPY);    //得到屏幕位图的句柄     
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);	//清除     
DeleteDC(hScrDC);
DeleteDC(hMemDC);	// 返回位图句柄     
return hBitmap;

}

int CMFCAppMenuDlg::SaveBitmapToFile(HBITMAP hBitmap, LPSTR lpFileName) {
//lpFileName 为位图文件名
HDC hDC; //设备描述表
int iBits; //当前显示分辨率下每个像素所占字节
WORD wBitCount; //位图中每个像素所占字节数
//定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数
DWORD dwPaletteSize = 0, dwBmBitsSize, dwDIBSize, dwWritten;
BITMAP Bitmap; //位图属性结构 BITMAPFILEHEADER bmfHdr; //位图文件头结构
BITMAPINFOHEADER bi; //位图信息头结构 LPBITMAPINFOHEADER lpbi; //指向位图信息头结构
HANDLE fh, hDib, hPal;
HPALETTE hOldPal = NULL; //定义文件,分配内存句柄,调色板句柄 //计算位图文件每个像素所占字节数
LPBITMAPINFOHEADER lpbi;
BITMAPFILEHEADER bmfHdr;

hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1)
	wBitCount = 1;
else if (iBits <= 4)
	wBitCount = 4;
else if (iBits <= 8)
	wBitCount = 8;
else if (iBits <= 24)
	wBitCount = 24;
else
	wBitCount = 32; //计算调色板大小   
if (wBitCount <= 8)
	dwPaletteSize = (1 << wBitCount)*sizeof(RGBQUAD);  //设置位图信息头结构

GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmBitsSize = ((Bitmap.bmWidth*wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;

//为位图内容分配内存
/*xxxxxxxx计算位图大小分解一下(解释一下上面的语句)xxxxxxxxxxxxxxxxxxxx
//每个扫描行所占的字节数应该为4的整数倍,具体算法为:

int biWidth = (Bitmap.bmWidth*wBitCount) / 32;
if ((Bitmap.bmWidth*wBitCount) % 32)
	biWidth++; 

//不是整数倍的加1
biWidth *= 4;

//到这里,计算得到的为每个扫描行的字节数。
dwBmBitsSize = biWidth * Bitmap.bmHeight;
//得到大小 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/

hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi; // 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal) {
hDC = ::GetDC(NULL);
hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}

// 获取该调色板下新的像素值   
GetDIBits(hDC, hBitmap, 0, (UINT)Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);   //恢复调色板   if (hOldPal)   
{
	SelectPalette(hDC, hOldPal, TRUE);
	RealizePalette(hDC);
	::ReleaseDC(NULL, hDC);
}

//创建位图文件   fh=CreateFile(lpFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);   
if (fh == INVALID_HANDLE_VALUE)
	return FALSE; // 设置位图文件头   
bmfHdr.bfType = 0x4D42; // "BM"   
dwDIBSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;

bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;		// 写入位图文件头   WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);   // 写入位图文件其余内容   
WriteFile(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)+dwPaletteSize + dwBmBitsSize, &dwWritten, NULL);	//清除   
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;

}

void CMFCAppMenuDlg::OnButton1() {
CRect rect; //
GetWindowRect(&rect);
GetDlgItem(IDB_PNG_ControlPanel1 )->GetWindowRect(&rect);
HBITMAP hMap = CopyScreenToBitmap(rect);

CString	s = TEXT("C://seu07201213(汪洋中的一片叶子).bmp");

SaveBitmapToFile(hMap, (LPSTR)s.GetBuffer() );

}
二十四、参考资料 — 双缓冲技术绘图原理及简单的VC实现
相关的VC函数: 1)、为屏幕 DC 创建兼容的内存DC:CreateCompatibleDC() if(!m_dcMemory.CreateCompatibleDC(NULL)) // CDC m_dcMemory; { ::PostQuitMessage(0); } 2)、创建位图:CreateCompatibleBitmap() m_Bmp.CreateCompatibleBitmap(&m_dcMemory, rt.Width(), rt.Height()); // CBitmap m_Bmp; 3)、把位图选入设备环境:SelectObject(),可以理解为选择画布 ::SelectObject(m_dcMemory.GetSafeHdc(), m_Bmp); 4)、把绘制好的内存图形“拷贝“到屏幕上:BitBlt() pdcView->BitBlt(0, 0, rt.Width(), rt.Height(), &m_dcMemory, 0, 0, SRCCOPY);

你可能感兴趣的:(VC++开发技术总结)