4:38 PM Visual C++技巧问答 |
一、如何使用API函数设置打印机的横向或竖向打印 读者 Rafe Fan问: 我有一个问题想请教,就是如何使用API函数设置打印机的横向或竖向打印呢? 答:你可以使用API函数DocumentProperties获取或者设置打印时打印机的初始化信息(包括打印方向)。在使用该函数需要使用DEVMODE结构。你可以参考下面的代码: LPDEVMODE GetLandscapeDevMode(HWND hWnd, char *pDevice) {// pDevice打印机设备名称 HANDLE hPrinter; LPDEVMODE pDevMode; DWORD dwNeeded, dwRet; if (!OpenPrinter(pDevice, &hPrinter, NULL)) //打开打印机设备 return NULL; /*分配合适的存储空间*/ dwNeeded = DocumentProperties(hWnd, hPrinter, /* handle to our printer */ pDevice, /* Name of the printer */ NULL, /* Asking for size so */ NULL, /* these are not used. */ 0); /* Zero returns buffer size. */ pDevMode = (LPDEVMODE)malloc(dwNeeded); /*获取打印机的缺省信息并修改它*/ dwRet = DocumentProperties(hWnd, hPrinter, pDevice, pDevMode, /* The address of the buffer to fill. */ NULL, /* Not using the input buffer. */ DM_OUT_BUFFER); /* Have the output buffer filled. */ if (dwRet != IDOK) { /*失败则释放存储空间并退出*/ free(pDevMode); ClosePrinter(hPrinter); return NULL; } //判断打印机是否支持方向打印 if (pDevMode->dmFields & DM_ORIENTATION) pDevMode->dmOrientation = DMORIENT_LANDSCAPE; if (pDevMode->dmFields & DM_DUPLEX) pDevMode->dmDuplex = DMDUP_HORIZONTAL; //设置打印方向 /*用新的设置信息取代原先的打印设置信息*/ dwRet = DocumentProperties(hWnd, hPrinter, pDevice, pDevMode, /* Reuse our buffer for output. */ pDevMode, /* Pass the driver our changes. */ DM_IN_BUFFER | /* Commands to Merge our changes and */ DM_OUT_BUFFER); /* write the result. */ /* 关闭打印机设备 */ ClosePrinter(hPrinter); if (dwRet != IDOK) { free(pDevMode); return NULL; } /* 返回变化的DevMode 结构 */ return pDevMode; } 二、怎样才能学好VC++ 读者高朋问: 我是一个VC++编程爱好者,但技术实在是太菜了。所以想请教你怎样才能学好VC++,或者怎样才能入门。能否介绍几本供我这种初学者学习的书或教材?还有,哪里可以找到高手,我可以拜师学艺,能否告诉几个相关网址? 答:心铃建议你: 1. 多读一些简单并具有特色的VC程序(如基于对话框Edit控件内容的显示、定时器等),并自己动手实现这些程序的功能。这是一个不断积累的过程,在这个过程中有必要把一些小的技巧记录下来。 2. 需要熟练掌握一些常用控件的编程(如Edit控件、按钮等)、菜单编程和消息响应(鼠标、键盘等)的实现。 3. 必须熟练掌握一些常用类的使用,如CString、CDialog和CEdit等。 4. 经常使用MSDN帮助说明,查找函数和类的具体使用方法。 5. 有条件可以上网获取一些关于VC编程的文档和源程序。 心铃推荐两本VC的学习书籍:《Visiual C++ 6从入门到精通》(北京希望电子出版社),《Visiual C++ 6轻松进阶》(电子工业出版社),当然你可以到相关的VC站点获取有关的源程序和专题论述等。 心铃推荐VC学习的网站:www.vckbase.com (VC知识库)。 三、有关sizeof的问题 读者sjrnlc问: 我是C++爱好者,有几个问题想问你。 1.) byte = 8 bit,一个英文字母占几个字节?一个数字呢? 2.)我写的程序都是在MS-DOS的环境下,我想将它写成window的界面,怎么办? 3.)有关sizeof的问题: struct Employee { short int emplno; char* name; float salarg; }; 我的编译器quincy99对sizeof的运算:短整型占 2 byte,指针占 4 byte,浮点占 4 byte. 加起来也只有 1 0 byte,为什么(书中的)结果是12 byte? 答:1.在C++环境下,char类型的数据占1个字节,short int类型的数据占2个字节,int 类型的数据占4个字节。 2.将MS-DOS环境下的程序加上Windows界面,你可以自己编程实现窗口、菜单等。也可以利用VC生成Windows应用程序的框架,将你的代码加入到框架程序中。 3.VC给struct和union分配空间时,会进行字节对齐(或者分段、打包)。参见MSDN中的"#pragma pack"节。象你这种情况,因为自己没有指定pack,则默认以8字节为一段,因此得到的并不是10个字节,而是12个字节。对齐的方式有以下几种:byte、word、double word、quad word,即1字节、2字节、4字节和8字节,一般默认是quad word对齐方式,编程时可以在代码前用#pragma关键字指定对齐方式;如:#pragma pack(1) 。指定对齐方式编译,这时使用sizeof(Employee)得出的结果是10。 四、怎样打开资源管理器?怎样调SetWindowsHookEx用来安装Hook函数? 读者whiteshark1981问:怎样打开资源管理器?怎样调SetWindowsHookEx用来安装Hook函数? 答:可以利用ShellExecute函数打开资源管理器,下面的代码打开资源管理器,并显示目录下c:\\temp的内容: ShellExecute(NULL,"explore",_T("c:\\temp"),NULL,NULL,SW_SHOWNORMAL); 要实现Win32的系统钩子,必须调用SDK中的API函数SetWindowsHookEx来安装这个钩子函数,这个函数的原型是HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);,其中,第一个参数是钩子的类型;第二个参数是钩子函数的地址;第三个参数是包含钩子函数的模块句柄;第四个参数指定监视的线程。如果指定确定的线程,即为线程专用钩子;如果指定为空,即为全局钩子。其中,全局钩子函数必须包含在DLL(动态链接库)中,而线程专用钩子还可以包含在可执行文件中。得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个SDK中的API函数CallNextHookEx来传递它。钩子函数也可以通过直接返回TRUE来丢弃该消息,并阻止该消息的传递。 五、读取与当前程序同一目录下的systemset.ini文件 读者capy问: 我在进行VC程序设计时遇到一个百思不得其解的问题,现写下请心铃老师指教。要读取与当前程序同一目录下的systemset.ini文件。我的方法为: char path[50]; CString strPath; ::GetCurrentDirectory(50,path); //得到当前应用程序所在的路径 strcat(path,"\\"); strPath=_T(path); strPath+="systemset.ini"; //将所对应文件改成所要的文件名 int nCount=::GetPrivateProfileInt("AdageCount","Current",0,strPath); //从ini文件中获得信息 strKeyNameE.Format("AdageE%d",nCount); ::GetPrivateProfileString("AdageSet",strKeyNameE,NULL,strAdageEnglish.GetBuffer(128),128,strPath); 在程序第一次运行时没有错误,(比如为E:\vc\adage\systemset.ini),可是当系统重新启动后(程序会自动运行),程序获得的路径不对了,不是当前与程序同一目录下的文件,而是指向了C:\systemset.ini(在Win200下。在WinXP下为C:\Doucument And Setting\Administrator\systemset.ini)。我不知道为什么会这样。请心铃老师指教。 答:你好,GetCurrentDirectory只是获取当前的目录,当计算机重新启动后,当前的路径一般为系统目录,因此系统启动后,使用该函数只能获取当前的目录,而不是应用程序所在的目录。我建议你使用GetModuleFileName函数,GetModuleFileName()是一个得到路径的API函数。本函数将这个API函数封装在其中,为的是简化调用的目的。 当执行这个函数时,返回本程序所在的绝对路径,包括本程序的文件名。 具体使用方法为: //获取主程序所在路径,存在sPath中 CString sPath; GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH); sPath.ReleaseBuffer (); int nPos; nPos=sPath.ReverseFind (’’\\’’); sPath=sPath.Left (nPos); …… 六、改变子窗口的尺寸 读者wengxiong200问: 我用MDI作为主窗口,这样之后我就无法改变子窗口的尺寸,改变Height和Width 的数值无济于事,但若不作为MDI的子窗口的就有效,我想手工改变子窗口的大小, 请问我该如何操作? 答:心铃建议使用API函数MoveWindow,函数原型为:BOOL MoveWindow( HWND hWnd, // handle of window int X, // horizontal position int Y, // vertical position int nWidth, // width int nHeight, // height BOOL bRepaint // repaint flag ); 你可以参考下面的代码: …… TMDIChild *Child; //--- create a new MDI child window ---- Child = new TMDIChild(Application); Child->Caption = Name; if (FileExists (Name)) Child->Memo1->Lines->LoadFromFile(Name); MoveWindow(Child->Handle,0,0,200,400,true); …… 七、编译链接和窗口重画问题 读者Yuan Jinrong问: 非常感谢您上次解答了我的关于VC编程中遇到的难题,现在我又遇到一些问题,特来信请教:两个问题: 1.编译链接 我写的一个文档/视图结构的VC程序,除了MFC外还有另外的一个库文件,我将这个库文件及其头文件都拷贝到所在目录,当use MFC in a shared DLL,顺利链接连接,程序能运行,但当use MFC in a Static Library时出现以下连接错误: 错误信息如下: Generating Code... Linking... msvcrt.lib(MSVCRT.dll) : error LNK2005: _memmove already defined in libcmt.lib(memmove.obj) msvcrt.lib(MSVCRT.dll) : error LNK2005: __mbscmp already defined in libcmt.lib(mbscmp.obj) msvcrt.lib(MSVCRT.dll) : error LNK2005: __setmbcp already defined in libcmt.lib(mbctype.obj) LINK : warning LNK4098: defaultlib "mfc42.lib" conflicts with use of other libs; use /NODEFAULTLIB:library LINK : warning LNK4098: defaultlib "mfcs42.lib" conflicts with use of other libs; use /NODEFAULTLIB:library LINK : warning LNK4098: defaultlib "msvcrt.lib" conflicts with use of other libs; use /NODEFAULTLIB:library Release/FEMprocess.exe : fatal error LNK1169: one or more multiply defined symbols found Error executing link.exe. FEMprocess.exe - 4 error(s), 120 warning(s) 2.窗口重画问题 有一个基于对话框的程序,其中有一个Picture控件用于显示计算结果的图形,但每次该对话框失去焦点后(比如操作另外的软件覆盖了该对话框),再回到该对话框界面时,原来的图形不能自动重新显示出来,我希望能在回到该对话框界面后,自动刷新,不知如何实现? 答:心铃建议你在工程设置中添加lib库文件,点击工程菜单下的工程设置子菜单,弹出工程设置对话框,在该对话框的link属性页上的对象/库模块一栏中添加库文件的名称,再编译试试。 第二个问题,心铃建议在对话框的OnPaint事件中添加显示的代码,同OnDraw事件相同,当窗口焦点或者尺寸发生变化时,产生该事件,另外计算的代码不要添加在该事件中,否则重画的速度缓慢。 |
|
Total comments: 0 | |