博文

VC++中的头文件包含问题(2007-08-27 15:51:00)

摘要: VC++中的头文件包含问题 在一些大的工程中,可能会包含几十个基础类,免不了之间会互相引用(不满足继承关系,而是组合关系)。也就是需要互相声明。好了,这时候会带来一些混乱。如果处理得不好,会搞得一团糟,根据我的经验,简单谈谈自已的处理办法: 编码时,我们一般会尽量避免include头文件,而是采用声明 class XXX。但有时候还是必须用Include头文件,那么,两者的划分在于什么呢?

应该是很明确的,但书上好像都少有提及。 首先:
我们要明白为什么要用声明取代头文件包含:对了,是为了避免无必要的重编译(在头文件发生变更时)。工程较大,低速机,或基础类经常变更(不合理的设计吧),编译速度还是会在意的,另外,更为重要的是,采用声明可降低代码(class)之间的藕合度,这也是面向对象设计的一大原则。 二:一般原则:
a. 头文件中尽量少include, 如果可以简单申明 class clsOld; 解决,那最好。减少没有必要的include;
b. 实现文件中也要尽量少include,不要include没有用到的头文件。 三:那什么时候可以只是简单声明class clsOld呢?
简单的说:不需要知道clsOld的内存布局的用法都可以(静态成员除外),也就是讲如果是指针或引用方式的都行。
比如:
   clsOld * m_pOld;    //指针占4个字节长
   clsOld & test(clsOld * pOld) {return *pOld};
  一切OK。 四:什么时候不能简单声明class clsOld,必须include呢?
不满足三的情况下:
 比如:
         clsOld m_Objold;  //不知道占据大小,必须要通过它的具体声明来计算
原因很简单,想想你要计算sizeof(classNew),但连clsOld的size都不知道,编译器显然会无能为力。

特殊情况:
  ......

阅读全文(4978) | 评论:0

CreateProcess函数详解(2007-08-03 14:39:00)

摘要:  说明:
WIN32API函数CreateProcess用来创建一个新的进程和它的主线程,这个新进程运行指定的可执行文件。

函数原型:
BOOL CreateProcess
(
    LPCTSTR lpApplicationName,       
    LPTSTR lpCommandLine,       
    LPSECURITY_ATTRIBUTES lpProcessAttributes。
    LPSECURITY_ATTRIBUTES lpThreadAttributes,       
    BOOL bInheritHandles,       
    DWORD dwCreationFlags,
    LPVOID lpEnvironment,       
    LPCTSTR lpCurrentDirectory,       
    LPSTARTUPINFO lpStartupInfo,       
    LPPROCESS_INFORMATION lpProcessInformation
);

参数:
lpApplicationName:指向一个NULL结尾的、用来指定可执行模块的字符串。
  这个字符串可以使可执行模块的绝对路径,也可以是相对路径,在后一种情况下,函数使用当前驱动器和目录建立可执行模块的路径。
  这个参数可以被设为NULL,在这种情况下,可执行模块的名字必须处于 lpCommandLine 参数的最前面并由空......

阅读全文(2374) | 评论:0

API函数MultiByteToWideChar的用法(2007-07-31 20:16:00)

摘要:API函数MultiByteToWideChar的用法

有关手机发送接受短消息的AT指令集
采用TPDU发送格式,要将中文转换,看到提示要用API函数MultiByteToWideChar,

就是把 AnsiString 转成 WideString, 用 BCB 非常简单了
AnsiString s = "源字符串";
WideString w = s; //w 就是转成 WideChar 的了,使用 w 就可以了

如果你想用 API 函数,参数如下:
API 函数 MultiByteToWideChar
  第一个参数为代码页, 用 GetLocaleInfo 函数获取当前系统的代码页,936: 简体中文, 950: 繁体中文
  第二个参数为选项,一般用 0 就可以了
  第三个参数为 ANSI 字符串的地址, 这个字符串是第一个参数指定的语言的 ANSI 字符串 (AnsiString)
  第四个参数为 ANSI 字符串的长度,如果用 -1, 就表示是用 0 作为结束符的字符串
  第五个参数为转化生成的 unicode 字符串 (WideString) 的地址, 如果为 NULL, 就是代表计算生成的字符串的长度
  第六个参数为转化生成的 unicode 字符串缓存的容量

int BufSize = MultiByteToWideChar(936,0,s,-1,NULL,0); //计算简体中文字符串 s 转成 widestring 之后占用的内存字节数
…… //在此处为 wsbuf 分配内存 BufSize 个字节
MultiByteToWideChar(936,0,s,-1,wsbuf,BufSize); //把简体中文 AnsiString 字符串 s 转化为 unicode 的 WideString
......

阅读全文(13476) | 评论:1

MFC常用数据类型(2007-05-20 16:55:00)

摘要:MFC常用数据类型: 1、
UINT   A 16-bit unsigned integer on Windows versions 3.0 and 3.1; a 32-bit unsigned integer on Win32.
定义原型:
typedef unsigned int        UINT; 2、
bool应该是C语言里定义的,返回值为true和false(事实上就上1和0)  
   
BOOL应该是MFC及SDK里定义返回值的.  
它的定义应该是:typedef   int   BOOL;(WINDEF.H中定义)  
也就是说它是int型的  
返回值是大写的TRUE   和FALSE  
定义如下:  
#define   FALSE       0  
#define   TRUE        1  
(AFX.H中如此定义)   3、
BSTR   A 32-bit character pointer 32位的字符指针。
定义原型:
#if defined(WIN32) && !defined(OLE2ANSI)
typedef WCHAR OLECHAR;
#else
typedef char OLECHAR;
#endif
typedef OLECHAR* BSTR; 4、
BYTE   An 8-bit integer that is not signed.无符号8位整数。注意整数和整型int不......

阅读全文(3448) | 评论:0

VC界面显示图片(BMP) (2007-05-18 12:03:00)

摘要: VC界面显示图片(BMP)
1、通过点击浏览按钮选择BMP图像文件
点击浏览按钮打开文件对话框选择BMP图像文件,得到文件所在的路径目录。
关键代码如下:
void CShowBMPDlg::OnButtonSelectiamge()
...{
    char  szFilter[] = "BMP Files (*.bmp)|*.bmp|All Files (*.*)|*.*||";
    CFileDialog dlg( TRUE,"BMP",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter );
    if(dlg.DoModal() == IDOK)
    ...{
        strPathName = dlg.GetPathName();       
        LoadShowBMPFile(strPathName);   
        m_hBitmap = BufferToHBITMAP();   
        Invalidate();
    }
}2、加载BMP文件到内存
通过得到的BMP图像文件路径目录,加载BMP图像文件到内存中。
关键代码如下:
BOOL CShowBMPDlg::LoadShowBMPFile(const char *pPathname)
...{
    CFile file;
  &......

阅读全文(6232) | 评论:0

CFileDialog详解(2007-05-18 11:11:00)

摘要:CFileDialog::CFileDialog CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL ); BOOL bOpenFileDialog
该参数为指定true是Open,false是Save as 对话框。 LPCTSTR lpszDefExt
添加到没有扩展名文件上的扩展名 LPCTSTR lpszFileName
应该初始选定的文件名 DWORD dwFlags
自定义标志,当要进行多选的时候添加OFN_ALLOWMULTISELECT LPCTSTR lpszFilter
File of type中的过滤参数
例如: 
CString lpszFilter="位图(*.bmp)|*.bmp|\
  全部文件(*.*)|*.*||";   CWnd* pParentWnd
父窗口的指针。
CFileDialog::GetFileName 得到打开文件的名字 For example, GetFileName will return "TEXT.DAT" for the file C:\FILES\TEXT.DAT.
CFileDialog::GetFileTitle 得到打开文件的标题,不含扩展名。 For example, GetFileTitle will return "TEXT" for the file C:\FILES\TEXT.DAT.
CFileDialog::GetFileExt 得到打开文件的扩展名。 For example, if the name of the file entered is DATA.TXT, GetFileExt returns "TXT".
CFileDialog::GetPathName 得到......

阅读全文(5594) | 评论:1

在VC使用GDI+的配置方法(2007-05-10 23:20:00)

摘要:唉,最近实在是感叹于自己的落伍. 这样一个令人兴奋的GDI+,却被我雪藏了很久,都不想用它.(可能是因为之前有GDI+漏洞的问题吧). 今天研究了一下才发现, 它恰恰为我提供了每天朝思幕想的一些功能, 如提供了一个Alpha透明度通道, 提供了字体和图形的反走样功能. 那还等什么呢? 赶快加入到GDI+的行列来吧. 哈哈. 不过, GDI+并不像原有的GDI那样,直接就可以使用.如果想要开发这样的程序,需要先按下面的配置一下. 如果你是Visual C++ 6.0的用户: 1. 下载GDI+的库. 运行GDI+需要一个GdiPlus.dll的文件; 开发GDI+的程序,还需要GdiPlus.lib和GdiPlus*.h文件.这些都可以在微软的网站上下到.(搜一下windows sdk,都出来了) 2. 将以上的文件放在你的工程中的一个目录,然后在stdafx.h中包含#include "GdiPlus.h" (这就取决于你放置那几个文件的地方了) 3. 在"工程"->"选项"里,添加一个链接库 GdiPlus.lib 如果你是Visual Studio 2003的用户:
不必去下载GDI+库了,因为VS2003已经自带了. 只要在stdafx.h文件中包括#include <gdiplus.h>,
并且要在#include <gdiplus.h>语句之前加:#define   ULONG_PTR   void* ,否则报错。
并在项目->选项->链接器->输入 中填上需要的lib库, gdiplus.lib即可 在程序的App类里,添加一个成员变量: ULONG_PTR m_gdiplusToken; 在App的InitInstance函数里, 在"INT_PTR nResponse = dlg.DoModal();"之前,添加下面的语句:  Gdiplus::GdiplusStartupInput gdiplusStartupInput;
 Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); 在"INT_PT......

阅读全文(9230) | 评论:3

VC中Windows常用控件的创建和使用(2007-05-09 18:34:00)

摘要:VC中Windows常用控件的创建和使用
引言   本文将要介绍的Windows控件指的是Windows系统预定义的标准控件,如按钮控件、编辑控件和列表控件等。这些预定义控件实际是一种特殊的
子窗口,主要供用户同应用程序的交互之用。和普通窗口类一样,每一个预定义控件也都是由所属的窗口类规定了自身的外观属性和具有的功能。Windows
系统通过预定义的方式提供了一些标准控件的窗口类名,在程序设计时只需通过调用CreateWindow()函数或CreateWindowEx()函
数并将预定义的窗口类名作为参数传入即可创建出相应的控件。当用户通过屏幕对象同控件进行交互操作时,控件将以"通知消息"的形式向父窗口发送
WM_COMMAND通知消息,消息的wParam参数含有控制标识,在lPamam参数的高位字和低位字中分别含有通知码和控制句柄,由父窗口完成对
消息的响应处理。   按钮类控件   按钮类控件是窗口类名被系统预定义为BUTTON的一类控件,该类控件具有十余种不同的窗口风格,包含了普通的下压式按钮、单选按钮、复选按钮和分
组框等多种常用的按钮形式。具体情况列表如下: 按钮风格 说明
BS_AUTOCHECKBOX 同复选按钮类似,点击一下选中,再次点击取消。
BS_AUTORADIOBUTTON 同单选按钮类似,点击后选中标志将从同组的其他单选按钮处移到当前选项。
BS_AUTO3STATE 同三态复选按钮类似,只是在用户点击后改变状态。
BS_CHECKBOX 复选按钮
BS_DEFPUSHBUTTON 下压按钮,具有较黑的边框。
BS_GROUPBOX 分组框
BS_LEFTTEXT 同单选按钮或复选按钮配合使用,标题将显示在左侧。
BS_OWNERDRAW 可创建一个拥有者自绘按钮。
BS_PUSHBUTTON 普通下压按钮
BS_RADIOBUTTON 单选按钮
BS_3STATE 三态复选按钮   以上按钮风格通常需要同窗口风格共同使用,由CreateWindow()函数或MFC的CButton类成员函数Create()完成对按钮的创
建: // 按钮类窗口风格
DWORD STYLE......

阅读全文(5089) | 评论:0

利用Shell API显示出"桌面"和相应的图标(2007-05-08 23:24:00)

摘要:/****************************************************************************
*
*    FUNCTION: ShowDeskImages()
*
*    PURPOSE:  Show the icon and the title of the desk.
*
****************************************************************************/
HTREEITEM CShellTree::ShowDeskImages()
{
 ITEMIDLIST *pidlDeskTop; 
 SHFILEINFO  fi={0};
    HIMAGELIST hImageList;  if(S_OK!=SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOP,&pidlDeskTop))  
 {  
  return  FALSE;  
 }  
   
    hImageList=(HIMAGELIST)SHGetFileInfo(( LPCTSTR)pidlDeskTop,0U,&fi,
                                     siz......

阅读全文(3044) | 评论:0

探讨基于P2P技术开发视频会议软件(2007-04-29 13:41:00)

摘要:摘要】本文旨在剖析开发基于P2P技术开发视频会议软件相关主要技术,并给出一个简单的例子。

一、 引言

我相信多数人听说过微软的NetMeeting,甚至有人直接使用过;而如今,众多的网虫沉迷于视频聊天。这类软件是怎样开发出来的呢?本文中,让我们来共同剖析开发基于P2P技术开发视频会议软件相关的主要技术,并给出一个简明的例子。本示例应用程序允许LAN/Intranet上的任何两个人举行视频会议。

凭直觉我们就会知道,开发这一类软件所涉及的主要问题,就是视频帧的大尺寸将极大地影响数据的传输质量。因而,这类软件的性能也主要依赖于视频帧编码和解码的质量。为此,在本例中,我们选用的是较快速的H.263编码器库,该库具有相当好的压缩比率,从而有效地克服了我们在图像传输中的速度矛盾。

请注意,有兴趣的读者可稍微修改本文中的示例程序以应用于因特网环境中。

二、 音频的录制与播放问题

这一部分的开发相对简单。其一,这种功能的API从Windows 3.1开始就已经提供(winmm.lib+mmsystem.h);其二,如今借助于方便的因特网,我们完全可以搜到现成的包装类。在本文中,我们直接借用了提供了两个现成的RecordSound与PlaySound类。这两个类都派生于CWinThread类,用户可以“死搬硬套”地使用它们。下面代码展示了这两个类的使用,具体包装类定义请参考下载源码文件。

//创建并启动录音线程

record=new RecordSound(this);

record->CreateThread();

//创建并启动播放线程

play=new PlaySound1(this);

play->CreateThread();

//开始录制

record->PostThreadMessage(WM_RECORDSOUND_STARTRECORDING,0,0);

//开始播放

play->PostThreadMessage(WM_PLAYSOUND_STARTPLAYING,0,0);

阅读全文(4391) | 评论:3