1、MFC对话框显示BMP图片
我们先从简单的开始吧.先分一个类:
(一) 非动态显示图片(即图片先通过资源管理器载入,有一个固定ID)
(二) 动态载入图片(即只需要在程序中指定图片的路径即可载入)
为方便说明,我们已经建好一个基于对话框的工程,名为Ttest.
对话框类为CTestDlg
(一) 非动态载入图片.
方法1.先从最简单的开始,用picture 控件来实现.
步骤:
先在资源里Import一张图片,ID为IDB_BITMAP2
然后在对话框上添加一个picture控件,右键点击打开属性,
将type下拉框选择BITMAP,紧跟着下面就出现一个Image下拉框,
拉开就会看到所有已经载入好的图片,
选择你要的图片.运行程序即可看到.
方法2.通过背景图
同样如上,先载入一张图片,ID为IDB_BITMAP2
TestDlg.h中
CBrush m_brBk;//在public中定义
TestDlg.cpp中
在初始化函数OnInitDialog()中加入:
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP2);
m_brBk.CreatePatternBrush(&bmp);
bmp.DeleteObject();
return TRUE; // return TRUE unless you set the focus to a control
}
在打开类向导,找到WM_CTLCOLOR消息,重载得对应函数OnCtlColor(),添加如下:
HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (pWnd == this)
{
return m_brBk;
}
return hbr;
}
(二) 动态载入图片.
方法3 图像控件(本例用KoDak 图像编辑控件)
1. 首先应该保证系统中有这个控件。注意,它不能单独使用,必须和其他几个控件(特别是Imgcmn.dll)一同使用。如果没有,从别的机器上copy过来即可。这几个文件是Imgadmin.ocx,Imgcmn.dll,Imgedit.ocx,Imgscan.ocx,Imgshl.dll,Imgthumb.ocx,Imgutil.dll,把它们copy到windows/system目录下,然后用regsvr32.exe将它们分别注册。
2. 打开工程,进入资源管理器,在对话框上单击右键,单击Insert Activex control… 选择Kodak图象编辑控件,大小任意。
3. 在对话框上选中该控件,为其添加变量:m_ctrlPicture。。
4. 在BOOL CTestDlg::OnInitDialog()添加如下:
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_ctrlPicture.SetImage("aa.jpg"); //保证图像在工程目录下,也可以写绝对路径
m_ctrlPicture.Display();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
编译运行就OK了,此种方法的好处就是可能针对多种图像格式.
方法4 通过CBitmap,HBITMAP,直接用OnPaint()绘制
首先在CTestDlg类中声明一个变量: CBitmap m_bmp;
然后我们在对话框中加入一个picture 标签,名为IDC_STATIC1
然后:
BOOL CDisplayPic::OnInitDialog()
{
CDialog::OnInitDialog();
if( m_bmp.m_hObject != NULL )//判断
m_bmp.DeleteObject();
/////////载入图片
HBITMAP hbmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
"c://aaa.bmp", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);
if( hbmp == NULL )
return FALSE;
///////////////////////该断程序用来取得加载的BMP的信息////////////////////////
m_bmp.Attach( hbmp );
DIBSECTION ds;
BITMAPINFOHEADER &bminfo = ds.dsBmih;
m_bmp.GetObject( sizeof(ds), &ds );
int cx=bminfo.biWidth; //得到图像宽度
int cy=bminfo.biHeight; //得到图像高度
/////////////////// ////////////////////////////////
/////////////得到了图像的宽度和高度后,我们就可以对图像大小进行适应,即调整控件的大小,让它正好显示一张图片///////////////////////////
CRect rect;
GetDlgItem(IDC_STATIC1)->GetWindowRect(&rect);
ScreenToClient(&rect);
GetDlgItem(IDC_STATIC1)->MoveWindow(rect.left,rect.top,cx,cy,true);//调整大小
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
图片加载成功了,标签大小也适应了,下面就是绘制绘制图像了,打开类向导,重载WM_PAINT消息
void CDisplayPic::OnPaint()
{
//////////////以下三种情况任选一种会是不同效果(只能一种存在)///////////
//CPaintDC dc(this); //若用此句,得到的是对话框的DC,图片将被绘制在对话框上.
CPaintDC dc(GetDlgItem(IDC_STATIC1)); //用此句,得到picture控件的DC,图像将被绘制在控件上
//若用以下两句,得到的是屏幕的DC,图片将被绘制在屏幕上/////////////////////////////////////////////////////
// CDC dc;
// dc.m_hDC=::GetDC(NULL);
CRect rcclient;
GetDlgItem(IDC_STATIC1)->GetClientRect(&rcclient);
CDC memdc;
memdc.CreateCompatibleDC(&dc);
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, rcclient.Width(), rcclient.Height());
memdc.SelectObject( &bitmap );
CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC , 0);
CDC maskdc;
maskdc.CreateCompatibleDC(&dc);
CBitmap maskbitmap;
maskbitmap.CreateBitmap(rcclient.Width(), rcclient.Height(), 1, 1, NULL);
maskdc.SelectObject( &maskbitmap );
maskdc.BitBlt( 0, 0, rcclient.Width(), rcclient.Height(), &memdc,
rcclient.left, rcclient.top, SRCCOPY);
CBrush brush;
brush.CreatePatternBrush(&m_bmp);
dc.FillRect(rcclient, &brush);
dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(),
&memdc, rcclient.left, rcclient.top,SRCPAINT);
brush.DeleteObject();
// Do not call CDialog::OnPaint() for painting messages
}
以上四种方法唯有KoDak可以支持多种图像,其它的只支持BMP
以上转自:http://blog.csdn.net/cecilia214/article/details/5346302
以下转自:http://topic.csdn.net/u/20090410/10/ad7a5afe-c906-45ff-a673-f601e2ec05be.html
2、MFC对话框显示JPEG图片
放在对话框的OnPaint里
1 CDC* pDC;
2 pDC=GetDC();
3 ShowPicture(pDC,"c:\\12.jpg",0,0,200,100);
4
5
6
7 #define HIMETRIC_INCH 2540
8 LPPICTURE gpPicture;
9 void CCDMADlg::ShowPicture(CDC *pDC, CString m_strBRoute, int x, int y, int width, int height)
10 {
11 HANDLE hFile =CreateFile(m_strBRoute, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
12 _ASSERTE(INVALID_HANDLE_VALUE != hFile);
13
14 // 取得文件大小
15 DWORD dwFileSize = GetFileSize(hFile, NULL);
16 _ASSERTE(-1 != dwFileSize);
17 LPVOID pvData = NULL;
18 //根据文件大小分配内存
19 HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
20 _ASSERTE(NULL != hGlobal);
21 pvData = GlobalLock(hGlobal);
22 _ASSERTE(NULL != pvData);
23 DWORD dwBytesRead = 0;
24 //读取文件并存入全局内存
25 BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);
26 _ASSERTE(FALSE != bRead);
27 GlobalUnlock(hGlobal);
28 CloseHandle(hFile);
29 LPSTREAM pstm = NULL;
30 // 通过全局内存创建 IStream* 的指针
31 HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);
32 _ASSERTE(SUCCEEDED(hr) && pstm);
33 //通过图形文件创建IPicture 对象
34 if (gpPicture)
35 gpPicture->Release();
36 hr = OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&gpPicture);
37 _ASSERTE(SUCCEEDED(hr) && gpPicture);
38 pstm->Release();
39 HDC hdc;
40 hdc=pDC->GetSafeHdc();
41 if (gpPicture)
42 {
43 // 取得图片的宽和高
44 long hmWidth;
45 long hmHeight;
46 gpPicture->get_Width(&hmWidth);
47 gpPicture->get_Height(&hmHeight);
48 //宽高转换为象素
49 int nWidth = MulDiv(hmWidth, GetDeviceCaps(hdc, LOGPIXELSX), HIMETRIC_INCH);
50 int nHeight = MulDiv(hmHeight, GetDeviceCaps(hdc, LOGPIXELSY), HIMETRIC_INCH);
51 RECT rc;
52 GetClientRect(&rc);/*取得客户区*/
53 gpPicture->Render(hdc, x,y, (int)height*hmWidth/hmHeight,height, 0, hmHeight, hmWidth, -hmHeight, &rc);
54 /*显示图片*/
55 }
57 }
posted @
2012-09-10 17:43 王海光 阅读(14606) |
评论 (0) |
编辑 收藏
SetTimer函数用于创建一个计时器,KillTimer函数用于销毁一个计时器。计时器属于系统资源,使用完应及时销毁。
SetTimer的函数原型如下:
UINT_PTR SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc ) ;
其中
hWnd是和timer关联的窗口句柄,此窗口必须为调用SetTimer的线程所有;如果hWnd为NULL,没有窗口和timer相关联并且nIDEvent参数被忽略
nIDEvent是timer的标识,为非零值;如果hWnd为NULL则被忽略;如果hWnd非NULL而且与timer相关联的窗口已经存在一个为此标识的timer,则此次SetTimer调用将用新的timer代替原来的timer。timer标识和窗口相关,两个不同的窗口可以拥有nIDEvent相同的tiemr
uElapse是以毫秒指定的计时间隔值,范围为1毫秒到4,294,967,295毫秒(将近50天),这个值指示Windows每隔多久时间给程序发送WM_TIMER消息。
lpTimerFunc是一个回调函数的指针,俗称TimerFunc;如果lpTimerFunc为NULL,系统将向应用程序队列发送WM_TIMER消息;如果lpTimerFunc指定了一个值,DefWindowProc将在处理WM_TIMER消息时调用这个lpTimerFunc所指向的回调函数,因此即使使用TimerProc代替处理WM_TIMER也需要向窗口分发消息。
关于SetTimer的返回值:如果hWnd为NULL,返回值为新建立的timer的ID,如果hWnd非NULL,返回一个非0整数,如果SetTimer调用失败则返回0
KillTimer的函数原型为:BOOL KillTimer( HWND hWnd, UINT_PTR uIDEvent ) ; 参数意义同SetTimer。
关于KillTimer对消息队列中剩余未处理的WM_TIMER消息的影响,MSDN和Programming Windows上的说法完全相反。MSDN的说法很干脆:The KillTimer function does not remove WM_TIMER messages already posted to the message queue. 而petzold则说 The KillTimer call purges the message queue of any pending WM_TIMER messages. Your program will never receive a stray WM_TIMER message following a KillTimer call.(KillTimer消除消息队列中任何未处理的WM_TIMER消息,调用KillTimer后你的程序永远不会收到一条“漂泊游荡”的WM_TIMER消息)
wParam为计时器的ID;如果需要设定多个计时器,那么对每个计时器都使用不同的计时器ID。wParam的值将随传递到窗口过程中的WM_TIMER消息的不同而不同。
lParam为指向TimerProc的指针,如果调用SetTimer时没有指定TimerProc(参数值为NULL),则lParam为0(即NULL)。
可以通过在窗口过程中提供一个WM_TIMER case处理这个消息,或者,默认窗口过程会调用SetTimer中指定的TimerProc来处理WM_TIMER消息
如果在程序的整个执行过程中使用计时器,一般在处理WM_CREATE消息时或WinMain中消息循环前调用SetTimer,在处理WM_DESTROY消息时或在WinMain中消息循环后return前调用KillTimer。根据SetTimer中的参数不同,有三种方法使用计时器。
方法一:调用SetTimer时指定窗口句柄hWnd,nIDEvent中指定计时器ID,将lpTimerFunc置NULL从而不使用TimerProc;在窗口过程中处理WM_TIMER消息。调用KillTimer时,使用SetTimer中指定的hWnd和id。最好使用#define定义timer的id,例如:
#define ID_TIMER 1 SetTimer(hWnd,ID_TIMER,1000,NULL) ; KillTimer(hWnd,ID_TIMER) ; |
方法二:调用SetTimer时指定窗口句柄hWnd,nIDEvent中指定计时器ID,lpTimerFunc参数不为NULL而指定为TimerProc函数的指针。这种方法使用TimerProc函数(名字可自定)处理WM_TIMER消息:
VOID CALLBACK TimerProc ( HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime) { //处理WM_TIMER讯息 } |
TimerProc的参数hwnd是在调用SetTimer时指定的窗口句柄。Windows只把WM_TIMER消息送给TimerProc,因此消息参数总是等于WM_TIMER。iTimerID值是计时器ID,dwTimer值是与从GetTickCount函数的返回值相容的值。这是自Windows启动后所经过的毫秒数。 使用这种方法时,相关函数调用的形式为:
SetTimer(hWnd,ID_TIMER,1000,TimerProc) ; KillTimer(hWnd,ID_TIMER) ; |
方法三:调用SetTimer时不指定窗口句柄(为NULL),iTimerID参数自然被忽略,lpTimerFunc不为NULL而指定为TimerProc的指针。正如上面SetTimer的讨论中所说的,此时SetTimer的返回值正是新建立的计时器的ID,需将这个ID保存以供KillTimer销毁计时器时所用。当然,KillTimer的hWnd参数也置为NULL。这种方法同样用TimerProc处理WM_TIMER消息。
UINT_PTR iTimerID ; iTimerID = SetTimer(NULL,0,1000,TimerProc) ; KillTimer(NULL,iTimerID) ; |
使用这种方法的好处是不必自己指定计时器ID,这样就不必担心用错ID。
使用多个计时器只要在建立计时器时指定不同的ID。比如用上面所述方法一时的情况:
#define TIMER_SEC 1 #define TIMER_MIN 2 然后使用两个SetTimer来设定两个计时器: SetTimer (hwnd, TIMER_SEC, 1000, NULL) ; SetTimer (hwnd, TIMER_MIN, 60000, NULL) ; WM_TIMER的处理如下所示: case WM_TIMER: switch (wParam) { case TIMER_SEC: //每秒一次的处理 break ; case TIMER_MIN: //每分钟一次的处理 break ; } return 0 ; |
如果想将一个已经存在的计时器设定为不同的时间间隔,可以简单地用不同的时间值再次调用SetTimer。
计时器并不精确。有两个原因:
原因一:Windows计时器是硬件和ROM BIOS架构下之计时器一种相对简单的扩充。回到Windows以前的MS-DOS程序写作环境下,应用程式能够通过拦截者称为timer tick的BIOS中断来实现时钟或计时器。一些为MS-DOS编写的程序自己拦截这个硬件中断以实现时钟和计时器。这些中断每54.915毫秒产生一次,或者大约每秒18.2次。这是原始的IBM PC的微处理器频率值4.772720 MHz被218所除而得出的结果。在Windows 98中,计时器与其下的PC计时器一样具有55毫秒的解析度。在Microsoft Windows NT中,计时器的解析度为10毫秒。Windows应用程式不能以高于这些解析度的频率(在Windows 98下,每秒18.2次,在Windows NT下,每秒大约100次)接收WM_TIMER消息。在SetTimer中指定的时间间隔总是截尾后tick数的整数倍。例如,1000毫秒的间隔除以54.925毫秒,得到18.207个tick,截尾后是18个tick,它实际上是989毫秒。对每个小于55毫秒的间隔,每个tick都会产生一个WM_TIMER消息。
可见,计时器并不能严格按照指定的时间间隔发送WM_TIMER消息,它总要相差那么几毫秒。
即使忽略这几个毫秒的差别,计时器仍然不精确。请看原因二:
WM_TIMER消息放在正常的消息队列之中,和其他消息排列在一起,因此,如果在SetTimer中指定间隔为1000毫秒,那么不能保证程序每1000毫秒或者989毫秒就会收到一个WM_TIMER消息。如果其他程序的执行事件超过一秒,在此期间内,您的程式将收不到任何WM_TIMER讯息。事实上, Windows对WM_TIMER消息的处理非常类似于对WM_PAINT消息的处理,这两个消息都是低优先级的,程序只有在消息队列中没有其他消息时才接收它们。
WM_TIMER还在另一方面和WM_PAINT相似:Windows不能持续向消息队列中放入多个WM_TIMER讯息,而是将多余的WM_TIMER消息组合成一个消息。因此,应用程序不会一次收到多个这样的消息,尽管可能在短时间内得到两个WM_TIMER消息。应用程序不能确定这种处理方式所导致的WM_TIMER消息「遗漏」的数目。
可见,WM_TIMER消息并不能及时被应用程序所处理,WM_TIMER在消息队列中的延误可能就不能用毫秒来计算了。
由以上两点,你不能通过在处理WM_TIMER时一秒一秒计数的方法来计时。如果要实现一个时钟程序,可以使用系统的时间函数如GetLocalTime ,而在时钟程序中,计时器的作用是定时调用GetLocalTime获得新的时间并刷新时钟画面,当然这个刷新的间隔要等于或小于1秒。
本文转自:http://www.cppblog.com/ivenher/articles/19969.html
posted @
2012-09-10 17:16 王海光 阅读(570) |
评论 (0) |
编辑 收藏
Wget.exe:http://gnuwin32.sourceforge.net/packages/wget.htmcurl.exe: http://curl.haxx.se/download.html wget.exe curl.exe下载命令curl.exe检测下载文件是否正确-f,wget.exe生成下载文档来检测Download wget http://127.0.0.1/update_ex.txt -O d:\2.txt -o c:\\DownLoad.txtDownload curl http://127.0.0.1/update_ex.txt -o d:\2.txt -f
posted @
2012-09-05 16:23 王海光 阅读(563) |
评论 (0) |
编辑 收藏
一、显示对话框
1.显示模式对话框:
CDialogDemo dlg;
dlg.DoModal();
2.显示非模式对话框:
CDialogDemo *dlg=new CDialogDemo(this);
dlg->Create(IDD_GENERAL_CONTROL);
dlg->ShowWindow(SW_SHOW);
二、关闭对话框:
1.CDialog::OnOK(); //确定按钮按下 CDialog::OnCancel(); //取消按钮被按下
2.CDialog::DestoryWindow();
3.CDialog::EndDialog(0);
注:CDialog::CloseWindow(); 仅仅是最小化对话框
PostMessage(WM_CLOSE)
三、在模态对话框类中关闭自身对话框
可以在模态对话框类中通过PostMessage(WM_CLOSE)来关闭自身对话框。关闭MessageBox对话框后模态对话框随之关闭。
相关代码如下:
1 BOOL CImportDataPromptDialog::OnInitDialog()
2 {
3 CDialog::OnInitDialog();
4
5 // TODO: Add extra initialization here
6 HANDLE hThread = StartImportDataThread();
7 if (!hThread)
8 {
9 LOG("启动导入数据线程失败")
10 }
11
12 return TRUE; // return TRUE unless you set the focus to a control
13 // EXCEPTION: OCX Property Pages should return FALSE
14 }
15
16 DWORD WINAPI CImportDataPromptDialog::ImportDataThread(LPVOID Param)
17 {
18 CImportDataPromptDialog* importDlg = (CImportDataPromptDialog*)Param;
19
20 if (CImportLog::ExtractionXMLData(importDlg->m_sXmlFilePath, importDlg->m_sDBPath))
21 {
22 importDlg->MessageBox("导入数据成功","平台", MB_ICONINFORMATION);
23 importDlg->PostMessage(WM_CLOSE);
24 }
25 else
26 {
27 importDlg->MessageBox("导入数据失败","平台", MB_ICONEXCLAMATION);
28 importDlg->PostMessage(WM_CLOSE);
29 }
30
31 return 0;
32 }
33
34 HANDLE CImportDataPromptDialog::StartImportDataThread()
35 {
36 LOG("启动导入数据线程");
37 CWinThread* hThread = AfxBeginThread((AFX_THREADPROC)CImportDataPromptDialog::ImportDataThread,(LPVOID)this);
38
39 return (hThread->m_hThread);
40 }
相关函数详解:
CloseWindow
函数功能:该函数最小化指定的窗口,但并不销毁该窗口。
函数原型:BOOL CloseWindow(HWND hWnd);
参数:
hWnd:将要最小化的窗口的句柄。
返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。
备注:窗口尺寸被最小化成一个图标,并移动到屏幕的图标区域。系统显示窗口的图标而不显示窗口,并在图标下显示窗口标题。应用程序必须使用DestroyWindow函数销毁窗口。
DestroyWindow
函数功能:销毁指定的窗口。这个函数通过发送WM_DESTROY 消息和 WM_NCDESTROY 消息使窗口无效并移除其键盘焦点。这个函数还销毁窗口的菜单,清空线程的消息队列,销毁与窗口过程相关的定时器,解除窗口对剪贴板的拥有权,打断剪贴板器的查看链。
函数原型:BOOL DestroyWindow( HWND hWnd // handle to window to destroy);
hWnd :将被销毁的窗口的句柄。
返回值:如果函数成功,返回值为非零:如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。
备注:一个线程不能使用本函数销毁别的线程创建的窗口。如果这个窗口是一个不具有WS_EX_NOPARENTNOTIFY 样式的子窗口,则销毁窗口时将发WM_PARENTNOTIFY 消息给其父窗口。
Windows CE: 本函数将不发送 WM_NCDESTROY 消息.
EndDialog
函数功能:该函数清除一个模态对话框,并使系统中止对对话框的任何处理。
函数原型:BOOL EndDialog(HWND hDlg,int nResult);
参数:
hDlg:表示要被清除的对话框窗口。
NResult:指定从创建对话框函数返回到应用程序的值。
返回值:如果函数调用成功,则返回值为非零值;如果函数调用失败则返回值为零。若想获得错误信息请调用GetLastError函数。
备注:由DialogBox,DialogBoxParam、DialogBoxlndirect和DialogBoxlndirectParam函数创建的对话框一定要用EndDialog函数来清除。应用程序从对话框应用程序内部调用EndDialog函数,该函数不能为其他目的而供使用。对话框应用程序可以在任何时间调用EndDialog函数;甚至在WM_INITDIALOG消息处理过程中。如果应用程序在WM_INTDIALOG消息处理过程中调用该函数,则对话框在显示和输入焦点被设置之前对话框被清除。EndDialog函数并不立即清除对话框。而是设置一个标志,并且允许对话框应用程序把控制权返回系统。系统在试图从应用程序队列检索下一个消息之前检测标志。如果已经设置了标志则系统中止消息循环,清除对话框,且用nResUlt中的值作为从创建对话框的函数中返回的值。
本文相关链接:http://blog.csdn.net/bbrsher/article/details/6088108
posted @
2012-09-05 14:44 王海光 阅读(9644) |
评论 (0) |
编辑 收藏
小结:
WM_CREATE是所有窗口都能响应的消息,表明本窗口已经创建完毕.可以安全的使用这个窗口了,例如在它上面画控件等等.这个状态肯定是在调用ShowWindows()显示窗口之前.
WM_WM_INITDIALOG是对话框才能收到的消息,表明对话框及其所有子控件都创建完毕了,这个状态肯定是调用显示对话框的函数之前.所以可以在WM_WM_INITDIALOG对控件进行一些修改等.
-------
不要被MFC干扰了,MFC封装了太多的东西,心里想着API的执行顺序就行了。
所有窗口都是在注册窗口类之后调用CreateWindowEx来创建的,创建成功之后(HWND有效但CreateWindowEx尚未返回)系统自动发送WM_CREATE消息,所以你的OnCreate将被执行,在这里窗口已经创建成功了,你可以安全地创建各种子窗口。
-------
-------
http://www.cppblog.com/pwqonline/archive/2008/12/04/67806.html
在响应WM_CREATE消息响应函数的时候,对话框及子控件还未创建完成,亦是说只是通知系统说要开始创建窗口啦,这个消息响应完之后,对话框和子控件才开始创建。因此在此消息响应函数中无法对控件进行修改和初始化。
而WM_INITDIALOG消息响应函数是在程序运行时,当其对话框和子控件全部创建完毕,将要显示内容的时候发送的消息。因此可以在WM_INITDIALOG消息响应函数中添加对编辑框控件的初始化和修改。
-------
WM_CREATE消息用来产生子窗口控件,WM_CREATE是谁发出的,什么意思??
当然是windows操作系统发出,所有消息都是由操作系统发出给程序的,分成进队消息,和不进队
消息,wm_create不仅仅指子窗口产生,所有窗口在操作系统内部产生时,windows都会发出这个消息
--------
应用程序中处理消息的顺序(转)
MFC应用程序中处理消息的顺序
1.AfxWndProc() 该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc
2.AfxCallWndProc() 该函数负责保存消息(保存的内容主要是消息标识符和消息参数)供应用程序以后使用,
然后调用WindowProc()函数
3.WindowProc() 该函数负责发送消息到OnWndMsg()函数,如果未被处理,则调用DefWindowProc()函数
4.OnWndMsg() 该函数的功能首先按字节对消息进行排序,对于WM_COMMAND消息,调用OnCommand()消息
响应函数,对于WM_NOTIFY消息
调用OnNotify()消息响应函数。任何被遗漏的消息将是一个窗口消息。OnWndMsg()函数搜
索类的消息映像,以找到一个
能处理任何窗口消息的处理函数。如果OnWndMsg()函数不能找到这样的处理函数的话,则
把消息返回到WindowProc()函数,由它将消息发送给DefWindowProc()函数
5.OnCommand() 该函数查看这是不是一个控件通知(lParam参数不为NULL,如果lParam参数为空的话,说明
该消息不是控件通知),如果它是,OnCommand()函数会试图将消息映射到制造通知的控件;
如果他不是一个控件通知(或者如果控件拒绝映射的消息)OnCommand()就会调用OnCmdMsg()函数
6.OnCmdMsg() 根据接收消息的类,OnCmdMsg()函数将在一个称为命令传递(Command Routing)的过程中潜在的
传递命令消息和控件通知。
例如:如果拥有该窗口的类是一个框架类,则命令和通知消息也被传递到视图和文档类,并为该
类寻找一个消息处理函数
MFC应用程序创建窗口的过程
1.PreCreateWindow() 该函数是一个重载函数,在窗口被创建前,可以在该重载函数中改变创建参数
(可以设置窗口风格等等)
2.PreSubclassWindow() 这也是一个重载函数,允许首先子分类一个窗口
3.OnGetMinMaxInfo() 该函数为消息响应函数,响应的是WM_GETMINMAXINFO消息,允许设置窗口的最大或者
最小尺寸
4.OnNcCreate() 该函数也是一个消息响应函数,响应WM_NCCREATE消息,发送消息以告诉窗口的客户区
即将被创建
5.OnNcCalcSize() 该函数也是消息响应函数,响应WM_NCCALCSIZE消息,作用是允许改变窗口客户区大小
6.OnCreate() 该函数也是一个消息响应函数,响应WM_CREATE消息,发送消息告诉一个窗口已经被创建
7.OnSize() 该函数也是一个消息响应函数,响应WM_SIZE消息,发送该消息以告诉该窗口大小已经
发生变化
8.OnMove() 消息响应函数,响应WM_MOVE消息,发送此消息说明窗口在移动
9.OnChildNotify() 该函数为重载函数,作为部分消息映射被调用,告诉父窗口即将被告知一个窗口刚刚被
创建
MFC应用程序关闭窗口的顺序(非模态窗口)
1.OnClose() 消息响应函数,响应窗口的WM_CLOSE消息,当关闭按钮被单击的时候发送此消息
2.OnDestroy() 消息响应函数,响应窗口的WM_DESTROY消息,当一个窗口将被销毁时,发送此消息
3.OnNcDestroy() 消息响应函数,响应窗口的WM_NCDESTROY消息,当一个窗口被销毁后发送此消息
4.PostNcDestroy() 重载函数,作为处理OnNcDestroy()函数的最后动作,被CWnd调用
MFC应用程序中打开模式对话框的函数调用顺序
1.DoModal() 重载函数,重载DoModal()成员函数
2.PreSubclassWindow() 重载函数,允许首先子分类一个窗口
3.OnCreate() 消息响应函数,响应WM_CREATE消息,发送此消息以告诉一个窗口已经被创建
4.OnSize() 消息响应函数,响应WM_SIZE消息,发送此消息以告诉窗口大小发生变化
5.OnMove() 消息响应函数,响应WM_MOVE消息,发送此消息,以告诉窗口正在移动
6.OnSetFont() 消息响应函数,响应WM_SETFONT消息,发送此消息,以允许改变对话框中控件的字体
7.OnInitDialog() 消息响应函数,响应WM_INITDIALOG消息,发送此消息以允许初始化对话框中的控件,
或者是创建新控件
8.OnShowWindow() 消息响应函数,响应WM_SHOWWINDOW消息,该函数被ShowWindow()函数调用
9.OnCtlColor() 消息响应函数,响应WM_CTLCOLOR消息,被父窗口发送已改变对话框或对话框上面控件
的颜色
10. OnChildNotify() 重载函数,作为WM_CTLCOLOR消息的结果发送
MFC应用程序中关闭模式对话框的顺序
1.OnClose() 消息响应函数,响应WM_CLOSE消息,当"关闭"按钮被单击的时候,该函数被调用
2.OnKillFocus() 消息响应函数,响应WM_KILLFOCUS消息,当一个窗口即将失去键盘输入焦点以前被发送
3.OnDestroy() 消息响应函数,响应WM_DESTROY消息,当一个窗口即将被销毁时,被发送
4.OnNcDestroy() 消息响应函数,响应WM_NCDESTROY消息,当一个窗口被销毁以后被发送
5.PostNcDestroy() 重载函数,作为处理OnNcDestroy()函数的最后动作被CWnd调用
打开无模式对话框的顺序
1.PreSubclassWindow() 重载函数,允许用户首先子分类一个窗口
2.OnCreate() 消息响应函数,响应WM_CREATE消息,发送此消息以告诉一个窗口已经被创建
3.OnSize() 消息响应函数,响应WM_SIZE消息,发送此消息以告诉窗口大小发生变化
4.OnMove() 消息响应函数,响应WM_MOVE消息,发送此消息以告诉窗口正在移动
5.OnSetFont() 消息响应函数,响应WM_SETFONT消息,发送此消息以允许改变对话框中控件的字体
以上这些的执行都是按给定的顺序执行!
只有清楚的了解应用程序的执行顺序,才能在编写代码的时候知道,在什么时候应该执行什么,以及在什么地方该处理什么!
这只是本人总结的一点小小的经验,希望能对MFC的初学者有所帮助!
本文转自:http://blog.csdn.net/srxumin/article/details/6059789
posted @
2012-09-05 14:31 王海光 阅读(4493) |
评论 (0) |
编辑 收藏
VC中我们经常使用到快捷键,这里快捷键有多种,包括menu,button。另外还区分local的和global的, 其中local的职能在当前程序有焦点(被激活)时有效,而global的,则无论什么时候都有效,测试local的要优先于global的,就是如果当前激活窗口的快捷键与未激活窗口的快捷键重叠,当前激活窗口优先响应。
这里将快捷键分为menu和button两种。
menu添加local快捷键又分为两种, 一种是直接与菜单项关联的加速键,另一种就是自定义的加速键.
第一种: 首先在资源文件Accelerator中添加快捷键资源 ID选择你要关联菜单项的名称 然后再设置你的快捷键.什么?下一步?在.h文件中加入一个 HACCEL hAccel;变量 然后在OnInitDialog或初始化中加入hAccel=::LoadAccelerators(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MENU_MAIN)); 后面的参数改成加速键的资源文件名.
最后在PreTranslateMessage(MSG* pMsg) 中加入:
if(::TranslateAccelerator(GetSafeHwnd(),hAccel,pMsg))
return true;
这样 以后只要在Accelerator资源文件中添加快捷键就可以了
注意: 添加快捷键的名字一定要与菜单名称一样 这样才能响应.现在只需要在此菜单项中加入OnCommand消息的处理就可以了.
第二种: 还是在资源文件Accelerator中添加快捷键资源 ID自己定义一个.然后再设置你的快捷键.下一步...就是在.h文件中定义一个快捷键对象
HACCEL m_hAccel;
然后在.cpp文件中初始
m_hAccel = ::LoadAccelerators(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_ACCELERATOR1));
IDR_ACCELERATOR1为你的加速资源名称.注意不是刚刚定义的加速键ID.
再添加PreTranslateMessage消息处理 在里面加入以下代码:
//保存快捷键被启用
if(m_hAccel != NULL)
{
if (TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
return TRUE;
}
再添加OnCommand消息处理 加入以下代码:
//响应加速键
switch(LOWORD(wParam))
{
case SHOW_DIAL0G: //加速键ID
//...添加处理语句
break;
case SHOW_DIALOG_02: //加速键ID
//...添加处理语句
break;
}
menu添加global快捷键
以对话框程序为例:
在OnInitDialog中添加注册热键的代码:
RegisterHotKey(GetSafeHwnd(),1001,NULL,VK_F2);//F2键
RegisterHotKey(GetSafeHwnd(),1002,MOD_ALT,'1');//Alt+1键
在
BEGIN_MESSAGE_MAP(CXXXDlg, CDialog)
...
END_MESSAGE_MAP()
中添加WM_HOTKEY的消息映射:
ON_MESSAGE(WM_HOTKEY,&CXXXDlg::OnHotKey)//快捷键消息映射手动加入
在头文件中添加OnHotKey的声明:
protected:
afx_msg LRESULT OnHotKey(WPARAM wParam,LPARAM lParam);//手动加入.
CPP中OnHotKey的实现代码:
//相应快捷键的消息映射
LRESULT CXXXDlg::OnHotKey(WPARAM wParam,LPARAM lParam)
{
if(wParam ==1001)
{
MessageBox("热键F2已经按下!");
//这里可以加上你按钮要执行的操作,或者直接调用按钮映射的消息函数
}
else if (wParam==1002)
{
MessageBox("热键ALT+1已经按下!");
}
return 0;
}
关闭对话框时使用
UnregisterHotKey(GetSafeHwnd(),1001);//注销F2键
UnregisterHotKey(GetSafeHwnd(),1002);//注销Alt+1键
注销热键.
button添加locak快捷键可以直接在button的caption中用 &+'X' 即可,则按下 Alt + 'x' 即按下此按钮,起到快捷键的作用
另外还可以学习menu添加local快捷键的第二种方式,在PreTranslateMessage中添加处理函数。
button添加global快捷键同menu添加global快捷键。
加载资源(MFC的Dialog Based中):
HACCEL hAcc = LoadAccelerators (m_hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
需要在
PreTranslateMessage中一行
if (TranslateAccelerator(GetSafeHwnd(), m_hAcc, pMsg))return TRUE;
posted @
2012-09-05 13:58 王海光 阅读(1375) |
评论 (0) |
编辑 收藏
摘要: PreTranslateMessage作用和使用方法
PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用,当需要在MFC之前处理某些消息时,常常要在这里添加代码.
&n...
阅读全文
posted @
2012-09-05 12:48 王海光 阅读(1657) |
评论 (0) |
编辑 收藏
在Windows平台做开发肯定会接触到UI程序的编写,以MFC的UI开发为例,可以开发单文档,多文档,对话框等形式的应用。写一个UI程序容易,写好却不是一件简单的事情。在整个代码结构的清晰性与可维护性方面需要多加注意。写好UI程序需求注意以下几点:
1、围绕数据编程与不是围绕UI编程
当我们拿到需求最先接触到的就是UI的设计,也许是美工画的,也许是设计草图。工程师在具体设计的时候容易受UI的影响,或者干脆从UI开始编程。
这是一个错误的编程习惯,无论UI如何展现与交互,最终都应该围绕数据编程。拿到需求后,应该先思考和推敲数据的设计与流转,UI不过就是数据的一种展现形式而已。
2、做好UI与逻辑的解耦
UI的编程会涉及到许多控件的操作,消息的处理,不知不觉,一个UI类的代码会越写越大,以至于一段时间以后,浏览和梳理都会变得不太方便。
在UI类里,除了与UI本身的操作有关的代码以外,任何逻辑代码都应该与此解耦,并根据具体情况进行封装调用。如果一个控件关联了太多数据操作,应该把这些操作封装到控件的继承类中,把一类代码进行集中管理和维护。
上述问题,在程序写作的初期还不太明显,随着代码逐渐膨胀,会越会越让人难以忍受。
3、数据单向依赖,单向更新
UI围绕的数据进行展现与更新,在这个过程中,所以对数据的操作应该进行封装,而不是散落在UI程序在各个角落,数据的更新、获取和UI传递消息时,应该单向操作,如果出现循环处理的情况,在以后维护调试的BUG的过程中会变得比较困难,导致维护效率下降。
本文来自CSDN博客,转载请标明出处:http://www.cppblog.com/humanchao
posted @
2012-09-05 10:45 王海光 阅读(502) |
评论 (0) |
编辑 收藏
获取驱动相关文件列表可用DRIVER_INFO_3,GetPrinterDriver
MSDN中解释:
DRIVER_INFO_3
The DRIVER_INFO_3 structure contains printer driver information.
typedef struct _DRIVER_INFO_3 {
DWORD cVersion;
LPTSTR pName;
LPTSTR pEnvironment;
LPTSTR pDriverPath;
LPTSTR pDataFile;
LPTSTR pConfigFile;
LPTSTR pHelpFile;
LPTSTR pDependentFiles;
LPTSTR pMonitorName;
LPTSTR pDefaultDataType;
} DRIVER_INFO_3, *PDRIVER_INFO_3;
Members
- cVersion
- Specifies the operating system version for which the driver was written. It can be one of the following.
Value |
Meaning |
0 |
Driver for Windows 95/98/Me. |
2 |
Driver for Windows NT 4.0. |
3 |
Driver for Windows 2000/XP. |
- pName
- Pointer to a null-terminated string that specifies the name of the driver (for example, "QMS 810").
- pEnvironment
- Pointer to a null-terminated string that specifies the environment for which the driver was written (for example, Windows NT x86, Windows IA64, Windows x64, Windows NT R4000, Windows NT Alpha_AXP, Windows 4.0, or Windows NT PowerPC).
Note Windows IA64 is available in Windows XP, Windows XP 64-Bit Edition, Windows Server 2003, and later versions. Windows x64 is available in Windows XP Service Pack 2 (SP2), Windows XP Professional x64 Edition, Windows Server 2003 Service Pack 1 (SP1), and later versions.
- pDriverPath
- Pointer to a null-terminated string that specifies a file name or full path and file name for the file that contains the device driver (for example, "C:\DRIVERS\Pscript.dll").
- pDataFile
- Pointer to a null-terminated string that specifies a file name or a full path and file name for the file that contains driver data (for example, "C:\DRIVERS\Qms810.ppd").
- pConfigFile
- Pointer to a null-terminated string that specifies a file name or a full path and file name for the device driver's configuration dynamic-link library (for example, "C:\DRIVERS\Pscrptui.dll").
- pHelpFile
- Pointer to a null-terminated string that specifies a file name or a full path and file name for the device driver's help file.
- pDependentFiles
- Pointer to a null-terminated string that specifies the files the driver is dependent on. Each file name in the string is also terminated with a null (for example, "Pscript.dll\0Qms810.PPD\0Pscrptui.dll\0Pspcriptui.hlp\0Pstest.txt\0\0").
- pMonitorName
- Pointer to a null-terminated string that specifies a language monitor (for example, "PJL monitor"). This member can be NULL and should be specified only for printers capable of bidirectional communication.
- pDefaultDataType
- Pointer to a null-terminated string that specifies the default data type of the print job (for example, "EMF").
Requirements
Windows NT/2000/XP/Vista: Included in Windows NT 4.0 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Winspool.h; include Windows.h.
Unicode: Declared as Unicode and ANSI structures.
GetPrinterDriver
The GetPrinterDriver function retrieves driver data for the specified printer. If the driver is not installed on the local computer, GetPrinterDriver installs it.
BOOL GetPrinterDriver(
HANDLE hPrinter, // printer object
LPTSTR pEnvironment, // environment name
DWORD Level, // information level
LPBYTE pDriverInfo, // driver data buffer
DWORD cbBuf, // size of buffer
LPDWORD pcbNeeded // bytes received or required
);
Parameters
- hPrinter
- [in] Handle to the printer for which the driver data should be retrieved. Use the OpenPrinter or AddPrinter function to retrieve a printer handle.
- pEnvironment
- [in] Pointer to a null-terminated string that specifies the environment (for example, Windows NT x86, Windows IA64, Windows x64, Windows NT R4000, Windows NT Alpha_AXP, Windows 4.0, or Windows NT PowerPC). If this parameter is NULL, the current environment of the calling application and client machine (not of the destination application and print server) is used.
Note Windows IA64 is available in Windows XP, Windows XP 64-Bit Edition, Windows Server 2003, and later versions. Windows x64 is available in Windows XP Service Pack 2 (SP2), Windows XP Professional x64 Edition, Windows Server 2003 Service Pack 1 (SP1), and later versions.
- Level
- [in] Specifies the printer driver structure returned in the pDriverInfo buffer. This parameter can be one of the following values.
- pDriverInfo
- [out] Pointer to a buffer that receives a structure containing information about the driver, as specified by Level. The buffer must be large enough to store the strings pointed to by the structure members.
To determine the required buffer size, call GetPrinterDriver with cbBuf set to zero. GetPrinterDriver fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, and the pcbNeeded parameter returns the size, in bytes, of the buffer required to hold the array of structures and their data.
- cbBuf
- [in] Specifies the size, in bytes, of the array at which pDriverInfo points.
- pcbNeeded
- [out] Pointer to a value that receives the number of bytes copied if the function succeeds or the number of bytes required if cbBuf is too small.
Return Values
If the function succeeds, the return value is a nonzero value.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Windows 95/98/Me: For a non-existent driver, the function returns ERROR_INVALID_NAMES.
Windows NT/2000/XP: For a non-existent driver, the function returns ERROR_UNKNOWN_PRINTER_DRIVER.
Remarks
The DRIVER_INFO_2, DRIVER_INFO_3, DRIVER_INFO_4, DRIVER_INFO_5, and DRIVER_INFO_6 structures contain the file name or the full path and file name of the printer driver in the pDriverPath member. An application can use the path and file name to load a printer driver by calling the LoadLibrary function and supplying the path and file name as the single argument.
Requirements
Windows NT/2000/XP/Vista: Included in Windows NT 3.1 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Winspool.h; include Windows.h.
Library: Use Winspool.lib.
Unicode: Implemented as Unicode and ANSI versions on Windows NT/2000/XP.
相关代码:
1 BOOL CCommonFun::GetPrinterDriverInfo(HANDLE hPrinter, CStringArray &arsDriverFiles, CString &sDriverInstallPath)
2 {
3 DWORD dwNeed = 0;
4 BOOL bOK = GetPrinterDriver(hPrinter, NULL, 3, NULL, NULL, &dwNeed);
5 if (dwNeed > 0)
6 {
7 BYTE *pData = new BYTE[dwNeed];
8
9 bOK = GetPrinterDriver(hPrinter, NULL, 3, pData, dwNeed, &dwNeed);
10 if(bOK)
11 {
12 DRIVER_INFO_3 *pInfo3 = (DRIVER_INFO_3*)pData;
13 sDriverInstallPath = GetFilePath(pInfo3->pDriverPath);
14 if (sDriverInstallPath.IsEmpty())
15 {
16 return FALSE;
17 }
18 //GetFileList
19 arsDriverFiles.Add(GetFileFullName(pInfo3->pDriverPath));
20 arsDriverFiles.Add(GetFileFullName(pInfo3->pDataFile));
21 arsDriverFiles.Add(GetFileFullName(pInfo3->pConfigFile));
22 arsDriverFiles.Add(GetFileFullName(pInfo3->pHelpFile));
23
24 LPSTR __pdependentFiles = pInfo3->pDependentFiles;
25 CString dependentFiles;
26 //get dependent files
27 if (__pdependentFiles)
28 {
29 while (__pdependentFiles[0] != '\0')
30 {
31 dependentFiles = GetFileFullName(__pdependentFiles);
32 arsDriverFiles.Add(dependentFiles);
33 __pdependentFiles += (strlen(__pdependentFiles)+1);
34 }
35 }
36 }
37 else
38 {
39 return FALSE;
40 }
41
42 delete []pData;
43 }
44 else
45 {
46 return FALSE;
47 }
48
49 return TRUE;
50 }
posted @
2012-09-04 17:51 王海光 阅读(580) |
评论 (0) |
编辑 收藏
实例代码:
1 #define USER_NAME ("姓名")
2 #define USER_ROLE ("学生/教师")
3 #define USER_CLASS ("班级")
4 #define USER_ACCOUNT ("用户名")
5
6 ListView_SetExtendedListViewStyle(m_nameList.GetSafeHwnd(), m_nameList.GetExStyle() | LVS_EX_CHECKBOXES|LVS_EX_GRIDLINES);
7 RECT rect;
8 m_nameList.GetWindowRect(&rect);
9 int avageWidth = (rect.right - rect.left)/COLUMN_COUNT;
10
11 LPSTR columnName[] ={USER_NAME,USER_ROLE,USER_CLASS,USER_ACCOUNT};
12
13 int widths[]={avageWidth-10,avageWidth-20,avageWidth+10,avageWidth};
14 LV_COLUMN lvc;
15 lvc.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
16 lvc.fmt=LVCFMT_LEFT;
17 for(int i=0;i <COLUMN_COUNT;i++)
18 {//insert a row
19 lvc.pszText=columnName[i];
20 lvc.cx=widths[i];
21 lvc.iSubItem=i;
22 m_nameList.InsertColumn(i,&lvc);
23 }
posted @
2012-09-04 17:44 王海光 阅读(766) |
评论 (0) |
编辑 收藏