3)为单个对话框窗口添加皮肤,例如在对话框视图中:重载对话框视图的创建函数OnCreate,加入如下代码:
VERIFY( 1 == SetSingleDialogSkin( m_hWnd, "Dialog" ) );
EnableWindowScrollbarSkin( m_hWnd , SB_BOTH );
说明:
int SetSingleDialogSkin(
HWND hWnd, //要使用皮肤的窗口句柄
char* lpSkinName //为skinFrameWnd对象指定的名称
);
int EnableWindowScrollbarSkin( //为滚动条添加皮肤
HWND hWnd, //要使用皮肤的窗口句柄
int* fnBar //要使用皮肤的滚动条,SB_BOTH表明是横竖都是用皮肤
);
4、释放SkinMagic资源
重载应用程序的ExitInstance()函数,添加如下代码:
ExitSkinMagicLib();
BOOL CYourDlg::OnInitDialog() { CDialog::OnInitDialog(); // Create the toolbar. To understand the meaning of the styles used, you // can take a look at the MSDN for the Create function of the CToolBar class. ToolBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS |CBRS_FLYBY | CBRS_BORDER_BOTTOM); // I have assumed that you have named your toolbar''s resource as IDR_TOOLBAR1. // If you have given it a different name, change the line below to accomodate // that by changing the parameter for the LoadToolBar function. ToolBar.LoadToolBar(IDR_TOOLBAR1); CRect rcClientStart; CRect rcClientNow; GetClientRect(rcClientStart); // To reposition and resize the control bar RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST,0, reposQuery, rcClientNow); CPoint ptOffset(rcClientNow.left - rcClientStart.left,rcClientNow.top-rcClientStart.top); CRect rcChild; CWnd* pwndChild = GetWindow(GW_CHILD); while (pwndChild) { pwndChild->GetWindowRect(rcChild); ScreenToClient(rcChild); rcChild.OffsetRect(ptOffset); pwndChild->MoveWindow(rcChild, FALSE); pwndChild = pwndChild->GetNextWindow(); } CRect rcWindow; GetWindowRect(rcWindow); rcWindow.right += rcClientStart.Width() - rcClientNow.Width(); rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height(); MoveWindow(rcWindow, FALSE); // And position the control bars RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); return TRUE; // return TRUE unless you set the focus to a control }Q:如何改变对话框的形状?
CRgn m_rgn; // Put this in your dialog''s header file. i.e. a member variable // This Gets the size of the Dialog: This piece of code is to be placed in the // OnInitDialog Function of your dialog. CRect rcDialog GetClientRect(rcDialog); // The following code Creates the area and assigns it to your Dialog m_rgn.CreateEllipticRgn(0, 0, rcDialog.Width(), rcDialogHeight()); SetWindowRgn(GetSafeHwnd(), (HRGN) m_rgn, TRUE);Q:如何实现非客户区移动?
// Handler for WM_LBUTTONDOWN message void CYourDialog::OnLButtonDown(UINT nFlags, CPoint point) { CDialog::OnLButtonDown(nFlags, point); PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y)); } // Handler for WM_NCHITTEST message LONG CYourDialog::OnNcHitTest( UINT uParam, LONG lParam ) { int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); UINT nHitTest = CDialog::OnNcHitTest(CSize(xPos, yPos)); return (nHitTest == HTCLIENT) ? HTCAPTION : nHitTest; }
SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, NULL);Q:如何限定对话框大小范围?
void CYourDialog::OnSizing(UINT fwSide, LPRECT pRect) { if(pRect->right - pRect->left <=200) pRect->right = pRect->left + 200; if(pRect->bottom - pRect->top <=200) pRect->bottom = pRect->top + 200; CDialog::OnSizing(fwSide, pRect); }Q:如何在对话框中加入状态条?
CStatusBar m_StatusBar;定义状态条指定状态:
static UINT BASED_CODE indicators[] = { ID_INDICATOR_CAPS, ID_INDICATOR_NUM };在 OnInitDialog 中加入下面代码:
m_StatusBar.CreateEx(this,SBT_TOOLTIPS,WS_CHILD|WS_VISIBLE|CBRS_BOTTOM,AFX_IDW_STATUS_BAR); // Set the indicators namely caps and nums lock status m_StatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT)); CRect rect; GetClientRect(&rect); m_StatusBar.SetPaneInfo(0,ID_INDICATOR_CAPS,SBPS_NORMAL,rect.Width()/2); m_StatusBar.SetPaneInfo(1,ID_INDICATOR_NUM,SBPS_STRETCH ,rect.Width()/2); RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,ID_INDICATOR_NUM); m_StatusBar.GetStatusBarCtrl().SetBkColor(RGB(180,180,180));
BOOL OpenClipboard(HWND hWnd); 参数 hWnd 是打开剪贴板的窗口句柄,成功返回TRUE,失败返回FALSE。之后,可以用GetClipboardData来得到剪贴板中的数据:
HANDLE GetClipboardData(UINT uFormat);uFormat是所需要数据的格式,例如本文拖放对象的格式为CF_HDROP。而表明该拖放对象类型(Move/Copy)的数据格式并不是Windows标准的剪贴板数据结构,而是一个简单的DWORD指针。我们可以通过下面的语句来注册一下数据类型 :
UINT uDropEffect=RegisterClipboardFormat("Preferred DropEffect");这里返回的uDropEffect就是我们将要代入GetClipboardData函数的该数据结构的代码,
HDROP hDrop = HDROP( GetClipboardData( CF_HDROP));如果确实存在一个hDrop对象,我们应该取得uDropEffect的数据,以便我们处理后面的文件:
DWORD dwEffect=*((DWORD*)(GetClipboardData( uDropEffcet)));关于这个值的含义,我们只要包含一下"OLEIDL.H"头文件即可,在该头文件中5种状态的定义而本文只关注:
#define DROPEFFECT_COPY ( 1 ) #define DROPEFFECT_MOVE ( 2 )因此,我们可以通过
if(dwEffect & DROPEFFECT_COPY) CopyFile(....); else (dwEffect & DROPEFFECT_MOVE) MoveFile(...);来完成剪切/拷贝操作。
UINT DragQueryFile(HDROP hDrop, UINT iFile,LPTSTR lpszFile,UINT cch);第二个参数是文件序列号,可以通过将iFile置为-1的方法来得到文件数量。
#include在这个例子中,我并没有进行文件操作,只是简单的显示一个消息框,实际应用时,需要使用MoveFile和CopyFile函数来完成,本文不做讨论。#include .... UINT uDropEffect=RegisterClipboardFormat("Preferred DropEffect"); if( OpenClipboard( hWnd)) { HDROP hDrop = HDROP( GetClipboardData( CF_HDROP)); if( hDrop) { DWORD dwEffect,*dw; dw=(DWORD*)(GetClipboardData( uDropEffect)); if(dw==NULL) dwEffect=DROPEFFECT_COPY; else dwEffect=*dw; char Buf[4096]; Buf[0] = 0; UINT cFiles = DragQueryFile( hDrop, (UINT) -1, NULL, 0); POINT Point; char szFile[ MAX_PATH]; for( UINT count = 0; count < cFiles; count++ ) { DragQueryFile( hDrop, count, szFile, sizeof( szFile)); lstrcat(Buf,szFile); lstrcat(Buf,"/n"); } if(dwEffect & DROPEFFECT_MOVE) { MessageBox(NULL,Buf,"Move Files",MB_OK); } else if(dwEffect & DROPEFFECT_COPY) { MessageBox(NULL,Buf,"Copy Files",MB_OK); } CloseClipboard(); } }
uDropEffect=RegisterClipboardFormat("Preferred DropEffect");然后分配内存对象并得到指针:
hGblEffect=GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,sizeof(DWORD)); dwDropEffect=(DWORD*)GlobalLock(hGblEffect);注意往剪贴板中放的数据必须使用GMEM_MOVEABLE标志,最后我们设置数据并解除锁定:
if(COPY) *dwDropEffect=DROPEFFECT_COPY; else *dwDropEffect=DROPEFFECT_MOVE; GlobalUnlock(hGblEffect);这样我就为DropEffect准备还数据了,等一会儿我们连同文件拖放对象一起放入剪贴板。建立文件拖放对象的方法与DropEffect基本相同,只是文件拖放对象有特殊的数据结构 而不象DropEffect那样简单,该对象数据结构如下:
+----------------------------+ | DROPFILES | Files List | +----------------------------+DROPFILES是拖放对象的头数据,该结构在shlobj.h中定义:
typedef struct _DROPFILES { DWORD pFiles; POINT pt; BOOL fNC; BOOL fWide; } DROPFILES, FAR * LPDROPFILES;pFiles指针是以对象首地址为参照的文件列表(上图中的Files List项)的offset量。通常该值等于DROPFILES结构的长度(我还没见过例外);pt表明文件拖放的位置坐标,在这个例子里我们忽略为0; fNC表明pt值是否为客户区坐标(FALSE表明是屏幕坐标);fWide表明Files List是否包含unicode,作为中国人,我们当然要设其为TRUE。DROPFILES结构之后紧跟Files List,Files List是一组宽字符串,之间以0相隔,比如:"文件1/0文件2/0..."
uDropFilesLen=sizeof(DROPFILES); dropFiles.pFiles =uDropFilesLen; dropFiles.pt.x=0; dropFiles.pt.y=0; dropFiles.fNC =FALSE; dropFiles.fWide =TRUE; uGblLen=uDropFilesLen+uBufLen<<1+8; //uBufLen是文件名字符传组的长度,由于要转换成宽字符,因此长度要乘2 hGblFiles= GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, uGblLen); szData=(char*)GlobalLock(hGblFiles); memcpy(szData,(LPVOID)(&dropFiles),uDropFilesLen); //将DROPFILES copy到头部 szFileList=szData+uDropFilesLen; //得到存放文件列表的首地址 MultiByteToWideChar(CP_ACP,MB_COMPOSITE, lpBuffer,uBufLen,(WCHAR *)szFileList,uBufLen); GlobalUnlock(hGblFiles);现在我们就可以将上面两组数据放入剪贴板中了,注意在写数据前应先清空剪贴板。为了方便大家使用,下面我给出实现此功能的独立的函数:
VOID CutOrCopyFiles(char * lpBuffer,UINT uBufLen,BOOL bCopy)lpBuffer是包括所有准备剪切/拷贝的文件名称的缓冲区;uBufLen是lpBuffer的长度;bCopy决定该操作是Copy还是Cut,TRUE为Copy,FALSE为Cut。例如我们可以这样调用该函数:
char szFiles[]="c://1.txt/0c://2.txt/0"; CutOrCopyFiles(szFiles,sizeof(szFiles),FALSE);来剪切文件,或者使用:
CutOrCopyFiles(szFiles,sizeof(szFiles),TRUE);来拷贝文件。
#include#include #include
...... VOID CutOrCopyFiles(char *lpBuffer,UINT uBufLen,BOOL bCopy) { UINT uDropEffect; DROPFILES dropFiles; UINT uGblLen,uDropFilesLen; HGLOBAL hGblFiles,hGblEffect; char *szData,*szFileList; DWORD *dwDropEffect; uDropEffect=RegisterClipboardFormat("Preferred DropEffect"); hGblEffect=GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,sizeof(DWORD)); dwDropEffect=(DWORD*)GlobalLock(hGblEffect); if(bCopy) *dwDropEffect=DROPEFFECT_COPY; else *dwDropEffect=DROPEFFECT_MOVE; GlobalUnlock(hGblEffect); uDropFilesLen=sizeof(DROPFILES); dropFiles.pFiles =uDropFilesLen; dropFiles.pt.x=0; dropFiles.pt.y=0; dropFiles.fNC =FALSE; dropFiles.fWide =TRUE; uGblLen=uDropFilesLen+uBufLen*2+8; hGblFiles= GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE, uGblLen); szData=(char*)GlobalLock(hGblFiles); memcpy(szData,(LPVOID)(&dropFiles),uDropFilesLen); szFileList=szData+uDropFilesLen; MultiByteToWideChar(CP_ACP,MB_COMPOSITE, lpBuffer,uBufLen,(WCHAR *)szFileList,uBufLen); GlobalUnlock(hGblFiles); if( OpenClipboard(NULL) ) { EmptyClipboard(); SetClipboardData( CF_HDROP, hGblFiles ); SetClipboardData(uDropEffect,hGblEffect); CloseClipboard(); } }希望以上内容对你有所帮助。
1、通过点击浏览按钮选择BMP图像文件
点击浏览按钮打开文件对话框选择BMP图像文件,得到文件所在的路径目录。
关键代码如下:
char szFilter[] = "BMP Files (*.bmp)|*.bmp|All Files (*.*)|*.*||";
CFileDialog dlg( TRUE,"BMP",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter );
if(dlg.DoModal() == IDOK)
{
CString strPathName = dlg.GetPathName();
}
2、加载BMP文件到内存
通过得到的BMP图像文件路径目录,加载BMP图像文件到内存中。
关键代码如下:
BOOL CShowBMPDlg::LoadShowBMPFile(const char *pPathname)
{
CFile file;
if( !file.Open( pPathname, CFile::modeRead) )
return FALSE;
DWORD m_nFileLen;
m_nFileLen = file.GetLength();
m_pBMPBuffer = new char[m_nFileLen + 1];
if(!m_pBMPBuffer)
return FALSE;
if(file.ReadHuge(m_pBMPBuffer,m_nFileLen) != m_nFileLen)
return FALSE;
return TRUE;
}
3、将内存中的BMP文件内容转换到HBITMAP
将内存中的BMP文件内容转换成位图句柄。
关键代码如下:
HBITMAP CShowBMPDlg::BufferToHBITMAP()
{
HBITMAP hShowBMP;
LPSTR hDIB,lpBuffer = m_pBMPBuffer;
LPVOID lpDIBBits;
BITMAPFILEHEADER bmfHeader;
DWORD bmfHeaderLen;
bmfHeaderLen = sizeof(bmfHeader);
strncpy((LPSTR)&bmfHeader,(LPSTR)lpBuffer,bmfHeaderLen);
if (bmfHeader.bfType != (*(WORD*)"BM")) return NULL;
hDIB = lpBuffer + bmfHeaderLen;
BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
lpDIBBits=(lpBuffer)+((BITMAPFILEHEADER *)lpBuffer)->bfOffBits;
CClientDC dc(this);
hShowBMP = CreateDIBitmap(dc.m_hDC,&bmiHeader,CBM_INIT,lpDIBBits,&bmInfo,DIB_RGB_COLORS);
return hShowBMP;
}
4、在屏幕上显示BMP图像
双缓冲实现BMP位图显示在屏幕上。
关键代码如下:
void CShowBMPDlg::DrawImage(int x, int y, CDC *pDC)
{
HBITMAP OldBitmap;
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
OldBitmap=(HBITMAP)MemDC.SelectObject(m_hBitmap);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt(x,y,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);
MemDC.SelectObject(OldBitmap);
}
说明这份测试分析报告的具体编写目的,指出预期的阅读范围。
说明:
a. 被测试软件系统的名称;
b. 该软件的任务提出者、开发者、用户及安装此软件的计算中心,指出测试环境与实际运行环境 之间可能存在的差异以及这些差异对测试结果的影响。
列出本文件中用到的专问术语的定义和外文首字母组词的原词组。
列出要用到的参考资料,如:
a. 本项目的经核准的计划任务书或合同、上级机关的批文;
b. 属于本项目的其他已发表的文件;
c. 本文件中各处引用的文件、资料,包括所要用到的软件开发标准。列出这些文件的标题、文件编号、发表日期和出版单位,说明能够得到这些文件资料的来源。
用表格的形式列出每一项测试的标识符及其测试内容,并指明实际进行的测试工作内容与测试计划中预先设计的内容之间的差别,说明作出这种改变的原因。
把本项测试中实际得到的动态输出(包括内部生成数据输出)结果同对于动态输出的要求进行比较,陈述其中的各项发现。
用类似本报告3.1条的方式给出第 2项及其后各项测试内容的测试结果和发现。
简述该项功能,说明为满足此项功能而设计的软件能力以及经过一项或多项测试已证实的能力。
说明测试数据值的范围(包括动态数据和静态数据),列出就这项功能而言,测试期间在该软件中查出的缺陷、局限性。
用类似本报告4.l的方式给出第2项及其后各项功能的测试结论。
......
陈述经测试证实了的本软件的能力。如果所进行的测试是为了验证一项或几项特定性能要求的实现,应提供这方面的测试结果与要求之间的比较,并确定测试环境与实际运行环境之间可能存在的差异 对能力的测试所带来的影响。
陈述经测试证实的软件缺陷和限制,说明每项缺陷和限制对软件性能的影响,并说明全部测得的性能缺陷的累积影响和总影响。
对每项缺陷提出改进建议,如:
a. 各项修改可采用的修改方法;
b. 各项修改的紧迫程度;
c. 各项修改预计的工作量;
d. 各项修改的负责人。
说明该项软件的开发是否已达到预定目标,能否交付使用。
总结测试工作的资源消耗数据,如工作人员的水平级别数量、机时消耗等。
|
测试名称
|
测试内容
|
Unit Test
|
单元测试 – 在最低的功能/参数上验证程序的正确性
|
Functional Test
|
功能测试 – 验证模块的功能
|
Integration Test
|
集成测试 – 验证几个互相有依赖关系的模块的功能
|
Scenario Test
|
场景测试 – 验证几个模块是否能够完成一个用户场景
|
System Test
|
系统测试 – 对于整个系统功能的测试
|
Alpha/Beta Test
|
外部软件测试人员(Alpha/Beta 测试员)在实际用户环境中对软件进行全面的测试。
|
|
|
|
|
|
|
测试名称
|
测试内容
|
Stress/load test
|
测试软件在负载情况下能否正常工作
|
Performance test
|
测试软件的效能
|
Accessibility test
|
测试软件辅助功能测试 – 测试软件是否向残疾用户提供足够的辅助功能
|
Localization/Globalization Test
|
本地化/全球化测试
|
Compatibility Test
|
兼容性测试
|
Configuration Test
|
配置测试 – 测试软件在各种配置下能否正常工作
|
Usability Test
|
可用性测试 – 测试软件是否好用
|
Security Test
|
软件安全性测试
|
场景ID
|
场景名
|
测试结果
|
Bug/小强id
|
3024
|
用户登录
|
成功
|
|
3026
|
用户按价格排序
|
失败
|
5032
|
3027
|
用户按名字搜索
|
失败
|
5033
|
…
|
…
|
…
|
…
|
1,简述VC6下如何进行程序的调试。
在主菜单"Build"中,有一个Start Build的子菜单,它下面包含了Go菜单(快捷键为F5),选择后,程序将从当前语句进入调试运行,直到遇到断点或程序结束。
将鼠标移动到要调试的代码行,单击鼠标右键选择“Insert/Remove Breakpoint”,或者按下F9,可以在该行上添加断点,此时断点代码行前面出现一个棕色的圈,再次选择将清除断点。进入调试状态后,Debug菜单将取代Build菜单出现在菜单栏中,它下面包含常用的调试操作,如Step Over,单步运行并不跟踪到调用的函数内部;其他还包括Step Into,Step Out, Stop Debugging等调试方法。
2, 简述在VC6建立的工程中后缀为.cpp,.h,.rc,.dsp,.dsw的文件的作用是什么?
.cpp是源程序代码C++文件
.h是包含函数声明和变量定义的头文件
.rc是定义资源的资源脚本文件
.dsp是工程文件,记录当前工程的有关信息
.dsw是工作区文件,一个工作区可能包含一个或多个工程
3, 已知一个对话框上有一个编辑框控件,ID为IDC_EDIT1,为其关联了CEdit类型的变量m_edit1,使用两种方法,说明如何改变编辑框内部的文本为"Hello",写出程序代码的片断。
第一种方法:m_edit1.SetSel(0,-1);
m_edit1.ReplaceSel("Hello");
第二种方法:SetWindowText("Hello");
4, 简述使用Windows API编写的一个基本的Windows应用程序框架的结构。
Windows API编写的基本应用程序框架至少应该包含程序入口函数WinMain和窗口函数WndProc。在主函数WinMain里面包含窗口类的定义和注册,窗口的创建和显示以及消息循环。
5, 消息在Windows中的数据类型是什么,它有哪些成员变量,各有什么含义
消息的数据类型是MSG,它是一个结构体,其成员变量主要包括hwnd,表示消息的窗口句柄;message代表消息的类型;wParam和lParam包含消息的附加信息,随不同的消息有所不同。
6, Windows的鼠标消息的长参数lParam与字参数wParam的含义是什么
鼠标消息的长参数lParam的低字节包含了鼠标光标位置的x坐标值,lParam的高字节包含了鼠标光标位置的y坐标值;字参数wParam内包含了指示当前按下的各种虚键状态的值。
7, 说明使用一个非模态对话框的注意问题和用到的Windows API函数
使用一个非模态对话框应该注意一定要在样式中包含WS_VISIBLE才能正常显示;创建对话框使用CreateDialog函数;消息循环部分应该使用IsDialogMessage过滤消息;关闭对话框使用函数DestroyWindow。
8, 简述在MFC应用程序中UpdateData函数的作用及其参数含义与使用场合。
UpdateData只有一个BOOL类型的参数,UpdateData(FALSE)一般用于对话框控件连接的变量值刷新屏幕显示;UpdateData(TRUE)用于获取屏幕数据到对话框控件连接的变量中。
9, 列举列表框控件能够接受的三个消息类型,并说明其作用
LB_ADDSTRING用于在列表框中加入一项字符串;LB_DIR用于在列表框中列出指定文件;LB_GETTEXT用于获取指定项的文本。
10, 在一个对话框上添加了三个单选按钮,要使它们之间自动实现互斥,应该注意什么问题,在VC环境下如何操作?
要实现一组单选按钮的自动互斥,应该让它们的控件ID值连续,并设置第一个单选按钮的Group属性,其他的不设。
11, 简述由一个文档类派生自己的文档类,并实现文档的存取需要哪些步骤。
首先为每一个文档类型从CDocument派生一个相应的文档类;然后为该文档类添加成员变量以保存数据;最后重载Serialize成员函数以实现文档数据的串行化。
12, 列举视图类(CView)的三个子类,并简要说明其作用。
CScrollView类提供视图的滚动显示;CEditView类支持在视图中的文本编辑操作;CHtmlView类支持在视图中显示和操作html文件。
13, Visual C++ 6.0如何进入调试状态,在调试状态下能够显示哪些调试窗口,列举三个,其作用分别是什么?
启动调试后,在View菜单的Debug Window子菜单下可以打开一些辅助调试的窗口
Watch:显示察看当前语句和前面语句中变量值的窗口
Call Stack:显示察看调用堆栈的窗口
Memory:显示察看内存中内容的窗口
14, 说明位图资源的创建及显示过程的步骤,并给出相应的Windows API函数名。
首先定义位图句柄HBITMAP hBitmap;第二步使用LoadBitMap加载位图;第三步,调用CreateCompatibleDC向系统申请内存设备环境句柄,并调用函数SelectObject把位图选入内存设备环境;第四步,调用BitBlt函数将位图从内存设备环境输出到指定的窗口设备环境中,从而实现显示位图。
15, 如何获取字体句柄从而实现字体的输出,并给出相应的Windows API函数名。
首先定义字体句柄变量HFONT hF;然后调用函数GetStockObject获取系统的字体句柄,或者调用CreateFont得到自定义的字体句柄;最后调用SelectObject把字体句柄选入设备环境。
16, 列举三种按钮的类型,并说明其作用和创建方法之间的不同之处。
常用的按钮有普通按钮、单选按钮、复选框,和组框。普通按钮作用是帮助用户触发指定动作;单选按钮一般各选项之间存在互斥性;复选框用来显示一组选项供用户选择,各选项之间不存在互斥;组框主要用于把控件分成不同的组并加以说明.
17, 要使一个静态控件显示一个位图并能接受用户输入,应该注意什么问题。
要使静态控件显示位图,必须设定其风格包含SS_BITMAP,并在创建静态控件窗口,即调用CreateWindow时指定并加载位图;要使静态控件能够接收用户输入,必须设定其风格包含SS_NOTIFY。
跟踪之,居然死在了如下语句:
CString str;
而且还极不稳定,这次调试死在n行,下次调试死在m行。但都是和内存申请有关。(由于程序很大,其中频繁地申请和释放内存,多处使用new和CString)
猜测:一定是内存不够啦,遂在某处调用函数得到当前剩余的物理内存数量并使用MessageBox显示。报告曰:自由物理内存还有100多M。鼠标按下OK键,程序居然不死了。恩???
删除MessageBox()函数—死!加上MessageBox()函数—不死!再删除–死,再加上–不死。晕倒!
捏呆呆郁闷不知道多少时间后,灵光闪烁……把多处的new/delete改写为GlobalAlloc()/GlobalFree(),一切OK。
事后原因分析:使用new和CString,频繁申请,释放内存,一定产生零碎内存块。当使用MessageBox的时候,系统接管程序的运行(因为它在等待着你按OK按纽),它这时候开始回收合并这些零碎的内存块。这样程序就没有问题了。而函数GlobalAlloc()/GlobalFree()本身就有回收合并零碎内存的功能。
友情提示:在频繁使用new,CString的场合,建议把某些(大)数据块的申请用GlobalAlloc替换。
用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数显示BMP位图,可以消除以上的缺点。 |
|||||||||||
一、BMP文件结构
3. 位图信息头
4. 颜色表 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:
5. 位图数据
二、BMP位图一般显示方法 1. 申请内存空间用于存放位图文件 GlobalAlloc(GHND,FileLength); 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容DC, 用SelectBitmap()选择显示位图。 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:
3. 位图文件读入所申请内存空间中
4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通过直接处理位图数据,可以制作简单动画。
1. 在CViewBimap类中添加视频函数等成员
2. 在CViewBimap类构造函数中添加打开视频函数
3. 在CViewBimap类析构函数中添加关闭视频函数
4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()
五、使用CViewBimap类显示BMP位图 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC AppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。
并在该程序的头部添加#include "bitmap0.h",然后编译运行。 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。
|