函数名:

 

  SetWindowPos

头文件:

  winuser.h

函数原型:

  BOOL SetWindowPos
  (
  HWND hWnd, //窗口句柄
  HWND hWndInsertAfter, //排列顺序的句柄
  int X, //水平坐标
  int Y, //垂直坐标
  int cx, //宽
  int cy, //高
  UINT uFlags //窗口定位标识
  );

说明:

  这个函数能改变窗口的大小、位置和设置子窗口、弹出窗口或顶层窗口的排列顺序。
  返回值:

  BOOL,如果返回值非零表示成功,返回零表示失败。错误信息请参看GetLastError函数。

参数表:

  参数 类型及说明
  hwnd HWND,欲定位的窗口句柄
  hWndInsertAfter HWND,置于hwnd前面的窗口句柄。这个参数必须是窗口的句柄或是下面的值之一:    HWND_BOTTOM 将窗口置于其它所有窗口的底部
  HWND_NOTOPMOST 将窗口置于其它所有窗口的顶部,并位于任何最顶部窗口的后面。如果这个窗口非顶部窗口,这个标记对该窗口并不产生影响
  HWND_TOP 将窗口置于它所有窗口的顶部
  HWND_TOPMOST 将窗口置于其它所有窗口的顶部,并位于任何最顶部窗口的前面。即使这个窗口不是活动窗口,也维持最顶部状态

x: 
 
  int,指定窗口新的X坐标

Y:  

  int,指定窗口新的Y坐标

cx:  

  int,指定窗口新的宽度

cy:  

  int,指定窗口新的高度

wFlags:

  UINT,指定窗口状态和位置的标记。这个参数使用下面值的组合: SWP_DRAWFRAME 围绕窗口画一个框
  SWP_FRAMECHANGED 发送一条WM_NCCALCSIZE消息进入窗口,即使窗口的大小没有发生改变。如果不指定这个参数,消息WM_NCCALCSIZE只有在窗口大小发生改变时才发送
  SWP_HIDEWINDOW 隐藏窗口
  SWP_NOACTIVATE 不激活窗口
  SWP_NOCOPYBITS 屏蔽客户区域
  SWP_NOMOVE 保持当前位置(X和Y参数将被忽略)
  SWP_NOOWNERZORDER 不改变所有窗口的位置和排列顺序
  SWP_NOREDRAW 窗口不自动重画
  SWP_NOREPOSITION 与SWP_NOOWNERZORDER标记相同
  SWP_NOSENDCHANGING 防止这个窗口接受WM_WINDOWPOSCHANGING消息
  SWP_NOSIZE 保持当前大小(cx和cy会被忽略)
  SWP_NOZORDER 保持窗口在列表的当前位置(hWndInsertAfter将被忽略)
  SWP_SHOWWINDOW 显示窗口


备注:

  如果设置了SWP_SHOWWINDOW或SWP_HIDEWINDOW标记,这个窗口不发生移动或改变大小。窗口成为最顶级窗口后,它的所有子窗口也会进入最顶级。一旦将其设为非最顶级,则它的所有子窗口也会转为非最顶级。

相关函数:

  MoveWindow,SetActiveWindow,SetForegroundWindow

例子:

  //设置顶层窗口
  SetWindowPos( Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE||SWP_NOSIZE);

  //取消顶层窗口
  SetWindowPos( Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE||SWP_NOSIZE);

函数功能:该函数改变一个子窗口,弹出式窗口式顶层窗口的尺寸,位置和Z序。子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口。

     函数原型:BOOL SetWindowPos(HWN hWnd,HWND hWndlnsertAfter,int X,int Y,int cx,int cy,UNIT.Flags);

     参数:

     hWnd:窗口句柄。

     hWndlnsertAfter:在z序中的位于被置位的窗口前的窗口句柄。该参数必须为一个窗口句柄,或下列值之一:

     HWND_BOTTOM:将窗口置于Z序的底部。如果参数hWnd标识了一个顶层窗口,则窗口失去顶级位置,并且被置在其他窗口的底部。

     HWND_DOTTOPMOST:将窗口置于所有非顶层窗口之上(即在所有顶层窗口之后)。如果窗口已经是非顶层窗口则该标志不起作用。

     HWND_TOP:将窗口置于Z序的顶部。

     HWND_TOPMOST:将窗口置于所有非顶层窗口之上。即使窗口未被激活窗口也将保持顶级位置。

     查g看该参数的使用方法,请看说明部分。

     x:以客户坐标指定窗口新位置的左边界。

     Y:以客户坐标指定窗口新位置的顶边界。

     cx:以像素指定窗口的新的宽度。

     cy:以像素指定窗口的新的高度。

     uFlags:窗口尺寸和定位的标志。该参数可以是下列值的组合:

     SWP_ASNCWINDOWPOS:如果调用进程不拥有窗口,系统会向拥有窗口的线程发出需求。这就防止调用线程在其他线程处理需求的时候发生死锁。

     SWP_DEFERERASE:防止产生WM_SYNCPAINT消息。

     SWP_DRAWFRAME:在窗口周围画一个边框(定义在窗口类描述中)。

     SWP_FRAMECHANGED:给窗口发送WM_NCCALCSIZE消息,即使窗口尺寸没有改变也会发送该消息。如果未指定这个标志,只有在改变了窗口尺寸时才发送WM_NCCALCSIZE。

     SWP_HIDEWINDOW;隐藏窗口。

     SWP_NOACTIVATE:不激活窗口。如果未设置标志,则窗口被激活,并被设置到其他最高级窗口或非最高级组的顶部(根据参数hWndlnsertAfter设置)。

     SWP_NOCOPYBITS:清除客户区的所有内容。如果未设置该标志,客户区的有效内容被保存并且在窗口尺寸更新和重定位后拷贝回客户区。

     SWP_NOMOVE:维持当前位置(忽略X和Y参数)。

     SWP_NOOWNERZORDER:不改变z序中的所有者窗口的位置。

     SWP_NOREDRAW:不重画改变的内容。如果设置了这个标志,则不发生任何重画动作。适用于客户区和非客户区(包括标题栏和滚动条)和任何由于窗回移动而露出的父窗口的所有部分。如果设置了这个标志,应用程序必须明确地使窗口无效并区重画窗口的任何部分和父窗口需要重画的部分。

     SWP_NOREPOSITION;与SWP_NOOWNERZORDER标志相同。

     SWP_NOSENDCHANGING:防止窗口接收WM_WINDOWPOSCHANGING消息。

     SWP_NOSIZE:维持当前尺寸(忽略cx和Cy参数)。

     SWP_NOZORDER:维持当前Z序(忽略hWndlnsertAfter参数)。

     SWP_SHOWWINDOW:显示窗口。

     返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误消息,请调用GetLastError函数。

     备注:如果设置了SWP_SHOWWINDOW和SWP_HIDEWINDOW标志,则窗口不能被移动和改变大小。如果使用SetWindowLoog改变了窗口的某些数据,则必须调用函数SetWindowPos来作真正的改变。使用下列的组合标志:SWP_NOMOVEISWP_NOSIZEISWP_FRAMECHANGED。

     有两种方法将窗口设为最顶层窗口:一种是将参数hWndlnsertAfter设置为HWND_TOPMOST并确保没有设置SWP_NOZORDER标志;另一种是设置窗口在Z序中的位置以使其在其他存在的窗口之上。当一个窗口被置为最顶层窗口时,属于它的所有窗口均为最顶层窗口,而它的所有者的z序并不改变。

     如果HWND_TOPMOST和HWND_NOTOPMOST标志均未指定,即应用程序要求窗口在激活的同时改变其在Z序中的位置时,在参数hWndinsertAfter中指定的值只有在下列条件中才使用:

     在hWndlnsertAfter参数中没有设定HWND_NOTOPMOST和HWND_TOPMOST标志。

     由hWnd参数标识的窗口不是激活窗口。

     如果未将一个非激活窗口设定到z序的顶端,应用程序不能激活该窗口。应用程序可以无任何限制地改变被激活窗口在Z序中的位置,或激活一个窗口并将其移到最高级窗口的顶部或非最高级窗口的顶部。

     如果一个顶层窗口被重定位到z序的底部(HWND_BOTTOM)或在任何非最高序的窗口之后,该窗口就不再是最顶层窗口。当一个最顶层窗口被置为非最顶级,则它的所有者窗口和所属者窗口均为非最顶层窗口。

     一个非最顶端窗口可以拥有一个最顶端窗口,但反之则不可以。任何属于顶层窗口的窗口(例如一个对话框)本身就被置为顶层窗口,以确保所有被属窗口都在它们的所有者之上。

     如果应用程序不在前台,但应该位于前台,就应调用SetForegroundWindow函数来设置。

     Windows CE:如果这是一个可见的顶层窗口,并且未指定SWP_NOACTIVATE标志,则这个函数将激活窗口、如果这是当前的激活窗口,并且指定了SWP_NOACTIVATE或SWP_HIDEWINDOW标志,则激活另外一个可见的顶层窗口。

     当在这个函数中的nFlags参数里指定了SWP_FRAMECHANGED标志时,WindowsCE重画窗口的整个非客户区,这可能会改变客户区的大小。这也是重新计算客户区的唯一途径,也是通过调用SetwindowLong函数改变窗口风格后通常使用的方法。

     SetWindowPos将使WM_WINDOWPOSCHANGED消息向窗口发送,在这个消息中传递的标志与传递给函数的相同。这个函数不传递其他消息。

     Windows CE 1.0不支持在hWndlnsertAber参数中的HWND_TOPMOST和HWND_NOTOPMOST常量。

posted @ 2009-06-06 18:49 wrh 阅读(7070) | 评论 (0)编辑 收藏

目 录

一. 视频捕获快速入门

二.基本的捕获设置

          1.设置捕获速度:

          2.设置终止捕获

          3.捕获的时间限制

三.关于捕获窗口

          1.创建一个AVICAP捕获窗口

          2.将一个捕获窗口连接至捕获设备

          3. 父窗口与子窗口的交互

          4.捕获窗口的状态

四.视频捕获驱动和音频驱动

          1.视频捕获驱动的性能:

          2.视频对话框:

          3.PREVIEW 和 OVERLAY模式:

          4.视频格式

          5.视频捕获设置

          6.声频格式

五.使用视频捕获

        1.创建捕获窗口(CREATING A CAPTURE WINDOW)

        2.连接到捕获驱动(CONNECTING TO A CAPTURE DRIVER)

        3.列举所有已安装的捕获驱动(ENUMERATING INSTALLED CAPTURE DRIVERS)

        4.得到捕获驱动的性能(OBTAINING THE CAPABILITIES OF A CAPTURE DRIVER)

        5.得到捕获窗口的状态(OBTAINING THE STATUS OF A CAPTURE WINDOW)

        6.显示对话框设置视频特征(DISPLAYING DIALOG BOXES TO SET VIDEO CHARACTERISTICS)

        7.得到和设置视频格式(OBTAINING AND SETTING THE VIDEO FORMAT)

        8. 预览视频(PREVIEWING VIDEO)

        9.将视频设置为OVERLAY模式(ENABLING VIDEO OVERLAY)

        10.命名捕获文件(NAMING THE CAPTURE FILE)

        11.格式化声频捕获(FORMATTING AUDIO CAPTURE)

        12.改变视频捕获设置(CHANGING A VIDEO CAPTURE SETTING)

        13.捕获数据(CAPTURING DATA)

        14.增加一个信息块(ADDING AN INFORMATION CHUNK)

        15.在程序中加入一个回调函数(ADDING CALLBACK FUNCTIONS TO AN APPLICATION)

        16.创建一个状态回调函数(CREATING A STATUS CALLBACK FUNCTION)

        17.创建一个错误回调函数( CREATING AN ERROR CALLBACK FUNCTION)

        18.创建一个框架回调函数(CREATING A FRAME CALLBACK FUNCTION)

六.将四个标准对话框改成函数调用形式

         AUDIOFORMAT对话框

         VIDEOFORMAT对话框

         VIDEOSOURCE对话框

         VIDEO COMPRESSION对话框  

前 言

         视频捕获是指由专用的视频采集卡捕获声频和视频信息,然后将其进行数据化处理,再经过软件的压缩进行处理,这时就可对这些数据进行保存、回放、传输等各种操作。

         Windows专门提供了Video for Windows来对视频处理进行支持,提供的接口可以被大多数的视频采集卡支持,并有多种视频压缩驱动供选择(当然视频压缩可以自己开发),采集卡支持摄像头,TV等多种输入。


一. 视频捕获快速入门

          视频捕捉将一个视频流和音频流数字化, 然后存储在硬盘或其他存储介质上.

          一个AVICap视窗口句柄描述了声频与视频流的细节, 这样就使你的应用程序从AVI文件格式, 声频视频缓冲管理, 低层声频视频驱动访问等等解脱出来, AVICap为应用程序提供了一个灵活的介面, 你可以仅仅使用如下几行代码就可以将视频捕捉加入你的程序:

hWndC = capCreateCaptureWindow ( "My Own Capture Window",

WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID);

SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0 /* wIndex */, 0L);

SendMessage (hWndC, WM_CAP_SEQUENCE, 0, 0L);

           一个宏其实也是使用SendMessage, 只不过提供给程序一个更易读的代码而已, 下面的这些示例就是使用宏的方法将视频捕捉加入程序:

hWndC = capCreateCaptureWindow ( "My Own Capture Window",

WS_CHILD | WS_VISIBLE , 0, 0, 160, 120, hwndParent, nID);

capDriverConnect (hWndC, 0);

capCaptureSequence (hWndC);


          当你创建了一个AVICap类的捕捉窗口并将它连接到一个视频驱动时, 此捕捉窗口即可以开始捕捉数据, 你的程序可以简单的发送WM_CAP_SEQUENCE消息(或者使用capCaptureSequence宏)来开始捕捉.

          如果是缺省的设置, WM_CAP_SEQUENCE会开始捕捉视频音频流到CAPTURE.AVI文件中, 直到下面的某一事件发生为止:

用户按下了ESC键或者一个鼠标键

你的应用程序终止或异常中断捕捉操作

磁盘已满


              在一个应用程序里, 你可以发送WM_CAP_STOP消息来终止捕捉数据(或者使用capCaptureStop宏), 你也可以发送WM_CAP_ABORT消息(或者使用capCaptureAbort宏)来终止.


二.基本的捕获设置

          基本的捕获设置包括:设置捕获速度(每秒捕获多少帧),是否同时捕获声频,捕获缓冲,允许最大丢失多少帧,是否使用DOS内存,以及用键盘的哪个键或鼠标的哪个键来终止捕获等等。这些基本的设置都可以使用CAPTUREPARAMS结构来描述,你可以使用capCaptureGetSetup宏来得到当前的设置,然后改变此结构的成员变量,再使用capCaptureSetSetup宏设置新的设置。

例如:

1.设置捕获速度:

           捕捉速度是指捕捉任务每秒钟捕获的帧数, 你可以发送WM_CAP_GET_SEQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)来得到当前的捕捉速度, 当前的捕捉速度保存在CAPTUREPARAMS结构的dwRequestMicroSecPerFrame成员变量中, 你可以通过设置此变量来改变当前设置, 单位是每毫秒连续的帧数, 你可以发送WM_CAP_SET_SEQUENCE_SETUP消息(或者使用capCaptureSetSetup宏), dwRequestMicroSecPerFrame的值是66667, 相当于每秒15帧.


2.设置终止捕获

           你可以允许用户按下某键或某组合键或者鼠标的左右键来终止一个捕获任务, 如果是实时的捕获, 则捕获的文件将会被丢弃; 如果是单步捕获, 在终止之前所捕获的内容将会被保存.

          你可以通过发送WM_CAP_GETQUENCE_SETUP消息(或者使用capCaptureGetSetup宏)来得到当前的设置, 当前的按键设置保存在CAPTUREPARAMS的vKeyAbort成员中, 当前的鼠标设置保存在fAbortLeftMouse和fAbortRightMouse成员中. 你可以设置新的按键或按键组合, 或者鼠标左右键, 当你修改的CAPTUREPARAMS后,应该发送WM_CAP_SET_SEQUENCE_SETUP消息来进行更新(或者使用capCaptureSetSetup宏). 缺省的按键是VK_ESCAPE. 你必须在指定按键之前使用RegisterHotKey函数, 鼠标缺省的值是fAbortLeftMouse和fAbortRightMouse都为TRUE.


3.捕获的时间限制

           CAPTUREPARAMS结构中的fLimitEnabled指示是否有时间限度, wTimeLimit指示最大的持续时间, 单位为秒.

          得到fLimitEnabled和wTimeLimit的值可以发送WM_CAP_GET_SEQUENCE_SETUP消息(或使用capCatureGetSetup宏), 当设置了这些成员变量后, 应该发送消息WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)来更新CAPTUREPARAMS结构.


三.关于捕获窗口

        在捕获之前必须创建一个捕获窗口(capture window),在发送消息或使用宏的过程中都需要使用此窗口。

1.创建一个AVICap捕获窗口

        你可以使用capCreateCaptureWindow函数来创建一个AVICap捕获窗口, 此函数将会返回一个句柄, 此句柄以后在发送消息时要用.

        你可以在一个程序里创建一个或多个捕获窗口, 然后给每一个窗口连接不同的捕获设置.


2.将一个捕获窗口连接至捕获设备

           你可以动态的在一个捕获窗口与一个捕获设备之前连接或断接, 你可以发送WM_CAP_DRIVER_CONNECT消息来使一个捕获窗口与一个捕获设备连接或关联. 当连接上以后, 你就可以通过捕获窗口向捕获设备发送各种消息.

        如果你的系统里装有多个捕获设备, 你可以在发送WM_CAP_DRIVER_CONNECT消息时用wParam参数指定使用哪一个, 此参数是登记在SYSTEM.INI文件的[drivers]一节里的列表中的某一项, 0为第一个.

          你可以使用capGetDriverDescription函数来得到已安装的捕获设备的名称及版本, 这样你的程序就可以列举所有已安装的捕获设备和驱动, 这样用户就可以选择其中的一个来与你的捕获窗口连接.

         你可以发送WM_CAP_DRIVER_GET_NAME消息(或capDriverGetName宏)来得到连接到捕获窗口的捕获设备的名称, 得到版本发送WM_CAP_DRIVER_GET_VERSION消息(或capDriverGetVersion宏)

         你可以发送WM_CAP_DRIVER_DISCONNECT消息(或capDriverDisconnect宏)来断接.


3. 父窗口与子窗口的交互

           一些象WM_PALETTECHANGED和WM_QUERYNEWPALETTE的系统级消息只能发送到顶级窗口或OVERLAPPED窗口, 如果一个捕获窗口是子窗口,就必须通过父窗口转送.

         同样的, 如果父窗口的尺寸改变了, 它就需要通知捕获窗口, 相反地, 如果捕获窗口的尺寸改变了, 捕获窗口就需要发送消息给父窗口, 一个简单的方法就是始终保持捕获窗口的尺寸与视频流的尺寸一致, 并随时将尺寸的改变通知父窗口.


4.捕获窗口的状态

          你可以发送WM_CAP_GET_STATUS消息(或capGetStatus宏)来得到当前捕获窗口的状态, 得到的是一个CAPSTATUS结构的拷贝, 它包含图片的尺寸, 卷轴的当前位置, overlay和preview是否已设置.

        因为CAPSTATUS信息是动态的, 你的程序应该只要捕获的视频流的尺寸或格式可能发生了改变就应该进行刷新(例如: 显示了捕获设备的视频格式以后).

        改变捕获窗口的尺寸并不影响实际的捕获的视频流的尺寸, 视频捕获设备的格式对话框捕获频流的尺寸.


四.视频捕获驱动和音频驱动

1.视频捕获驱动的性能:

          你可以通过发送WM_CAP_DRIVER_GET_CAPS消息(或者capDriverGetCaps宏)来得到当前连接的视频驱动的硬件性能. 得到的信息保存在CAPDRIVERCAPS结构中.


2.视频对话框:

          每一个视频驱动能够提供四个对话框来控制视频捕获和数字化处理, 定义压缩品质等, 这些对话框都定义在视频捕获驱动中.

          Video Source对话框用于控制选择视频来源, 此对话框列举了此视频捕获卡连接的所有视频源(典型的例如:SVHS和合成输入), 并提供了改变色调, 对比度, 饱和度. 如果视频驱动支持此对话框, 你就可以显示并更新它, 使用WM_CAP_DLG_VIDEOSOURCE消息(或capDlgVideoSource宏).

           Video Format对话框定义视频帧的尺寸以及精度, 视频捕获卡的压缩设置. 如果卡支持的话, 可以发送消息WM_CAP_DLG_VIDEOFORMAT消息或(capDlgVideoFormat宏).

           Video Display对话框控制在视频捕获期间在显示器上的显示, 此控制不会影响视频数字数据, 但是他们可能会影响数字信号的表现形式, 例如: 如果捕获设备支持overlay, 可能允许改变色调和饱和度, 关键色彩 或者overlay队列. 如果卡支持, 你可以发送WM_CAP_DLG_VIDEODISPLAY消息(或者使用capDlgVideoDisplay宏).

           Video Compression对话框控制压缩品质, 如果卡支持, 发送消息WM_CAP_DLG_VIDEOCOMPRESSION(或capDlgVideoCompression宏).


3.Preview 和 Overlay模式:

                 一个视频捕获驱动对进入的视频流有两种工作模式: Preview模式和overlay模式, 如果一个捕获驱动能够执行两种方法, 用户可以在其中选择一种.

               Preview模式把从捕获硬件传来的数据送入系统内存并使用图形设备介面(GDI)将数字化帧显示在捕获窗口内. 应用程序可以在父窗口失去焦点时减缓显示速度, 当重新又得到焦点后加快显示速度, 此种模式要占用大量CPU时间.

有三种消息控制Preview操作:

WM_CAP_SET_PREIVEW消息(capPreview宏)允许或禁止preview模式

WM_CAP_SET_PREVIEWRATE(capPreviewRate宏)当帧在preview模式显示时设置速度.

WM_CAP_SET_SCALE(capPreviewScale宏)允许或禁止preview视频的缩放比例.

          当preview和scaling同时使用, 捕获的视频帧将会根据捕获窗口的尺寸自动缩放, 允许preview模式会自动关闭overlay模式.

                      overlay模式是一个硬件函数它将数据送入捕获缓冲区中因而不占用CPU资源. 你可以发送消息WM_CAP_SET_OVERLAY(或capOverlay宏)给捕获窗口来启用或终止overlay模式, 允许overlay模式会自动禁止preview模式.

               你同时也可以在preview模式或overlay模式里发送WM_CAP_SET_SCROLL消息(或capSetScrollPos宏)来设置视频帧的客户区卷轴位置.


4.视频格式

            你可以通过发送WM_CAP_GET_VIDEOFORMAT消息(或capGetVideoFormat和capGetVideoFormatSize宏)来得到视频格式的结构或结构的尺寸. 你可以通过发送CAP_SET_VIDEOFORMAT消息(或capSetVideoFormat宏)来设置视频格式.


5.视频捕获设置

           CAPTUREPARMS结构包含了对视频捕获流的控制参数, 你可以完成以下这些任务:

指定帧数

指定分配多少视频缓冲

允许或禁止声频捕获

指定捕获的时间间隔

指定在捕获的过程中是否使用MCI设置(VCR或者videodisc)

指定终止流的键盘或鼠标

specify the type of video averaging applied during capture.


得到:WM_CAP_GET_SEQUENCE_SETUP消息(或capCaptureGetSetup宏)

设置:WM_CAP_SET_SEQUENCE_SETUP消息(或capCaptureSetSetup宏)


6.声频格式

               你可以通过发送WM_CAP_GET_AUDIOFORMAT消息(或capGetAudioFormat宏和capGetAudioFormatSize宏)来得到当前捕获音频数据的格式或尺寸格式。缺省的声频格式是:单声道、8位、11kHz PCM。 当你使用WM_CAP_GET_AUDIOFORMAT时,总是使用WAVEFORMATEX结构。

             设置发送消息WM_CAP_SET_AUDIOFORMAT消息(或capSetAudioFormat宏),可以传送WAVEFORMAT,WAVEFORMATEX,PCMWAVEFORMAT结构指针。

五.使用视频捕获

1.创建捕获窗口(Creating a Capture Window)

hWndC = capCreateCaptureWindow (

(LPSTR) "My Capture Window", // window name if pop-up

WS_CHILD | WS_VISIBLE, // window style

0, 0, 160, 120, // window position and dimensions

(HWND) hwndParent,

(int) nID /* child ID */);


2.连接到捕获驱动(Connecting to a Capture Driver)

           下面的例子是将MSVIDEO驱动连接到句柄为hWndC的捕获窗口, 然后调用capDriverDisconnect宏来断接.

fOK = SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0, 0L);

//

// Or, use the macro to connect to the MSVIDEO driver:

// fOK = capDriverConnect(hWndC, 0);

//

// Place code to set up and capture video here.

//

capDriverDisconnect (hWndC);


3.列举所有已安装的捕获驱动(Enumerating Installed Capture Drivers)

           下面的例子使用capGetDriverDescription函数得到已安装的捕获驱动的名称及版本:

char szDeviceName[80];

char szDeviceVersion[80];


for (wIndex = 0; wIndex < 10; wIndex++)

{

if (capGetDriverDescription (wIndex, szDeviceName,

sizeof (szDeviceName), szDeviceVersion,

sizeof (szDeviceVersion))

{

// Append name to list of installed capture drivers

// and then let the user select a driver to use.

}

}


4.得到捕获驱动的性能(Obtaining the Capabilities of a Capture Driver)

              发送WM_CAP_DRIVER_GET_CAPS消息可以得到捕获驱动的性能,并保存入一个CAPDRIVERCAPS结构.每当程序连接一个新的捕获驱动到一个捕获窗口时, 就应该更新CAPDRIVERCAPS结构. 下面的程序举例说明了如何使用capDriverGetCaps宏来得到捕获驱动的性能:


CAPDRIVERCAPS CapDrvCaps;

SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS,

sizeof (CAPDRIVERCAPS), (LONG) (LPVOID) &CapDrvCaps);

// Or, use the macro to retrieve the driver capabilities.

// capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));


5.得到捕获窗口的状态(Obtaining the Status of a Capture Window)

                 下面的例子使用SetWindowPos函数使捕获窗口与进来的视频流尺寸保持一致, 视频流的基本信息是使用capGetStatus宏得到的, 保存在CAPSTATUS结构中.


CAPSTATUS CapStatus;

capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));

SetWindowPos(hWndC, NULL, 0, 0, CapStatus.uiImageWidth,

CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);


6.显示对话框设置视频特征(Displaying Dialog Boxes to Set Video Characteristics)

              每个视频捕获卡一般能提供三个不同的对话框用于控制视频捕获及数字化处理. 下面的例子说明如何显示这些对话框, 在显示这些对话框之前,使用了capDriverGetCaps宏来检查CAPDRIVERCAPS结构, 以检测该卡是否有显示这些对话框:


CAPDRIVERCAPS CapDrvCaps;

capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));


// Video source dialog box.

if (CapDriverCaps.fHasDlgVideoSource)

capDlgVideoSource(hWndC);


// Video format dialog box.

if (CapDriverCaps.fHasDlgVideoFormat)

{

capDlgVideoFormat(hWndC);

// Are there new image dimensions?

capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));

// If so, notify the parent of a size change.

}


// Video display dialog box.

if (CapDriverCaps.fHasDlgVideoDisplay)

capDlgVideoDisplay(hWndC);


7.得到和设置视频格式(Obtaining and Setting the Video Format)

                   BITMAPINFO结构的长度既适应于标准的也适应于压缩的数据格式, 所有程序必须总是询问此结构的尺寸以便在得到当前的视频格式之前分配内存. 下面的例子就是使用capGetVideoFormatSize宏来得到缓冲区尺寸并调用capGetVideoFormat宏来得到当前的视频格式.


LPBITMAPINFO lpbi;

DWORD dwSize;

dwSize = capGetVideoFormatSize(hWndC);

lpbi = GlobalAllocPtr (GHND, dwSize);

capGetVideoFormat(hWndC, lpbi, dwSize);


// Access the video format and then free the allocated memory.


              程序可以使用capSetVideoFormat宏(或WM_CAP_SET_VIDEOFORMAT消息)发送一个BITMAPINFO头结构给捕获窗口, 因为视频格式是设备细节, 你的程序应该检查返回值以便确定此格式是否已被接受.


8. 预览视频(Previewing Video)

             下面的例子使用capPreviewRate宏来设置每66毫秒显示一帧, 并使用capPreview宏将它放置在捕获窗口里.


capPreviewRate(hWndC, 66); // rate, in milliseconds

capPreview(hWndC, TRUE); // starts preview

// Preview

capPreview(hWnd, FALSE); // disables preview


9.将视频设置为overlay模式(Enabling Video Overlay)

            下面的例子: capDriverGetCaps宏确定此捕获卡是否有overlay功能, 如果有就使用宏来设置它


CAPDRIVERCAPS CapDrvCaps;

capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));


if (CapDrvCaps.fHasOverlay)

capOverlay(hWndC, TRUE);


10.命名捕获文件(Naming the Capture File)

             下面的例子: 使用capFileSetCaptureFile宏来指定预备文件名为:MYCAP.AVI, capFileAlloc宏预先指定它的大小为5M.


char szCaptureFile[] = "MYCAP.AVI";

capFileSetCaptureFile( hWndC, szCaptureFile);

capFileAlloc( hWndC, (1024L * 1024L * 5));


11.格式化声频捕获(Formatting Audio Capture)

             下面的例子使用capSetAudioFormat来设置声频格式为:11kHz, PCM 8位, 立体声


WAVEFORMATEX wfex;

wfex.wFormatTag = WAVE_FORMAT_PCM;

wfex.nChannels = 2; // Use stereo

wfex.nSamplesPerSec = 11025;

wfex.nAvgBytesPerSec = 22050;

wfex.nBlockAlign = 2;

wfex.wBitsPerSample = 8;

wfex.cbSize = 0;


capSetAudioFormat(hWndC, &wfex, sizeof(WAVEFORMATEX));


12.改变视频捕获设置(Changing a Video Capture Setting)

               下面的例子使用capCaptureGetSetup和capCaptureSetSetup宏得将捕获帧数从缺省的15帧改成每秒10帧.


CAPTUREPARMS CaptureParms;

float FramesPerSec = 10.0;


capCaptureGetSetup(hWndC, &CaptureParms, sizeof(CAPTUREPARMS));


CaptureParms.dwRequestMicroSecPerFrame = (DWORD) (1.0e6 /FramesPerSec);

capCaptureSetSetup(hWndC, &CaptureParms, sizeof (CAPTUREPARMS));


13.捕获数据(Capturing Data)

                下面的例子使用capCaptureSequence宏来开始捕获视频并使用capFileSaveAs宏来将捕获的数据拷贝至NEWFILE.AVI文件中.


char szNewName[] = "NEWFILE.AVI";

// Set up the capture operation.

capCaptureSequence(hWndC);

// Capture.

capFileSaveAs(hWndC, szNewName);


14.增加一个信息块(Adding an Information Chunk)

               如果你需要在你的程序捕获的声频和视频数据中加入你的其他信息, 你可以创建一个信息块并将它们插入捕获文件中, 信息块可以包含一些典型的信息, 例如:版权信息,视频来源, 外部定位信息等. 下面的例子使用capFileSetInfoChunk宏来插入一个信息块, 里面包含了一个SMPTE的时间代码.


// This example assumes the application controls

// the video source for preroll and postroll.

CAPINFOCHUNK cic;

// .

// .

// .

cic.fccInfoID = infotypeSMPTE_TIME;

cic.lpData = "00:20:30:12";

cic.cbData = strlen (cic.lpData) + 1;

capFileSetInfoChunk (hwndC, &cic);


15.在程序中加入一个回调函数(Adding Callback Functions to an Application)

               一个程序可以为捕获窗口登记一个回调函数以便在以下的这些情况下通知程序.


状态改变

错误发生

视频框架和声频缓冲区变得可用

程序应用在捕获视频流的过程中接收


           下面的例子创建一个捕获窗口并登记状态,错误,视频流和框架回调函数在消息处理对列中, 也包括了一个终止回调函数的说明.


case WM_CREATE:

{

char achDeviceName[80]

char achDeviceVersion[100]

char achBuffer[100]

WORD wDriverCount = 0

WORD wIndex

WORD wError

HMENU hMenu


// Create a capture window using the capCreateCaptureWindow macro.

ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window",

WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, (HWND) hWnd, (int) 0);


// Register the error callback function using the

// capSetCallbackOnError macro.

capSetCallbackOnError(ghWndCap, fpErrorCallback);


// Register the status callback function using the

// capSetCallbackOnStatus macro.

capSetCallbackOnStatus(ghWndCap, fpStatusCallback);


// Register the video-stream callback function using the

// capSetCallbackOnVideoStream macro.

capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback);


// Register the frame callback function using the

// capSetCallbackOnFrame macro.

capSetCallbackOnFrame(ghWndCap, fpFrameCallback);


// Connect to a capture driver


break;

}

case WM_CLOSE:

{

// Use the capSetCallbackOnFrame macro to

// disable the frame callback. Similar calls exist for the other

// callback functions.


capSetCallbackOnFrame(hWndC, NULL);


break;

}


16.创建一个状态回调函数(Creating a Status Callback Function)

            下面的例子是创建一个简单的状态回调函数,登记此回调函数使用capSetCallbackOnStatus宏.


// StatusCallbackProc: status callback function

// hWnd: capture window handle

// nID: status code for the current status

// lpStatusText: status text string for the current status

//

LRESULT PASCAL StatusCallbackProc(HWND hWnd, int nID,

LPSTR lpStatusText)

{

if (!ghWndMain)

return FALSE;


if (nID == 0) { // Clear old status messages.

SetWindowText(ghWndMain, (LPSTR) gachAppName);

return (LRESULT) TRUE;

}

// Show the status ID and status text...

wsprintf(gachBuffer, "Status# %d: %s", nID, lpStatusText);


SetWindowText(ghWndMain, (LPSTR)gachBuffer);

return (LRESULT) TRUE;

}


17.创建一个错误回调函数( Creating an Error Callback Function)

             下面的例子是创建一个简单的错误回调函数,登记此回调函数使用capsetCallbackOnError宏:


// ErrorCallbackProc: error callback function

// hWnd: capture window handle

// nErrID: error code for the encountered error

// lpErrorText: error text string for the encountered error

//

LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID,

LPSTR lpErrorText)

{

if (!ghWndMain)

return FALSE;


if (nErrID == 0) // Starting a new major function.

return TRUE; // Clear out old errors.


// Show the error identifier and text.

wsprintf(gachBuffer, "Error# %d", nErrID);


MessageBox(hWnd, lpErrorText, gachBuffer,

MB_OK | MB_ICONEXCLAMATION);


return (LRESULT) TRUE;

}


18.创建一个框架回调函数(Creating a Frame Callback Function)

              登记此回调函数使用capSetCallbackOnFrame宏:


// FrameCallbackProc: frame callback function

// hWnd: capture window handle

// lpVHdr: pointer to struct containing captured

// frame information

//

LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)

{

if (!ghWndMain)

return FALSE;


wsprintf(gachBuffer, "Preview frame# %ld ", gdwFrameNum++);

SetWindowText(ghWndMain, (LPSTR)gachBuffer);

return (LRESULT) TRUE

}


 

六.将四个标准对话框改成函数调用形式

              系统提供了四个标准的对话框:AudioFormat, VideoFormat, VideoSource, Video Compression,但有时程序希望通过函数控制它们,而不是使用系统提供的那个单一的对话框,此时就应该使用函数调用的方法:


AudioFormat对话框

            可以通过使用capSetAudioFormat来实现,此时要使用WAVEFORMATEX结构。

例如:改成PCM格式,立体声,16声道,12.05kHz,则:

WAVEFORMATEX audioFormat;

// 确定宽度

acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT,&dwSize);

dwSize = max (dwSize, capGetAudioFormatSize (m_hwCapCapturing));

// 设置参数

audioFormat.wFormatTag = WAVE_FORMAT_PCM;

audioFormat.nChannels = 2;

audioFormat.nSamplesPerSec = 120500;

audioFormat.wBitsPerSample =16;

audioFormat.nBlockAlign = nBitsPerSample * nChannels / 8;

audioFormat.nAvgBytesPerSec =

audioFormat.nBlockAlign * nSamplesPerSec;

// 更新

capSetAudioFormat(ghCapWnd,&audioFormat,dwSize);

VideoFormat对话框

                  可以通过使用capSetVideoFormat来实现,此时要使用BITMAPINFOHEADER结构。

例如:设置图片大小为RGB24位岁,大小为230X160

BITMAPINFOHEADER bi;

DWORD dwSize,dw;

bi.biSize = sizeof(BITMAPINFOHEADER);

bi.biWidth = 320; // 起作用

bi.biHeight = 160; // 起作用

bi.biPlanes = 1;

bi.biBitCount = 24;

bi.biCompression = BI_RGB;

bi.biSizeImage = 0;

bi.biXPelsPerMeter = 176;

bi.biYPelsPerMeter = 144;

bi.biClrUsed = 0;

bi.biClrImportant = 0;

dwSize = bi.biSize + ((bi.biBitCount > 8 || bi.biClrUsed) ? (bi.biClrUsed * sizeof(PALETTEENTRY)) : (2 ^ bi.biBitCount * sizeof(PALETTEENTRY)));

dw = capSetVideoFormat(m_hwCapCapturing, &bi, dwSize);

VideoSource对话框

                没有找到现成的方法,但视频捕获卡提供的CD里面有一个动态链接库可以实现。

Video Compression对话框

             可以通过使用ICOpen,ICInfo等函数联合起来,得到当前系统里面的视频压缩驱动的列表,并可选择其一,MSDN里面有一个程序示范了此用户,程序名叫:ICWalk。

posted @ 2009-06-06 18:31 wrh 阅读(3063) | 评论 (0)编辑 收藏

HWND   VFWAPI   capCreateCaptureWindow(  
      LPCSTR   lpszWindowName,      
      DWORD   dwStyle,                      
      int   x,                                      
      int   y,                                      
      int   nWidth,                            
      int   nHeight,                          
      HWND   hWnd,                              
      int   nID                                    
  );  
      Header:   Declared   in   vfw.h.  
      Import   Library:   Use   vfw32.lib.  
//////////////////////////////////////////////////////////////////////////////
调用capCreateCaptureWindow创建的窗口如何关闭释放掉?
小弟不懂VC,只是调的API,用完后但不知道如何关闭掉这个窗口
网友回复:HWND hWnd = capCreateCaptureWindow(...);

// 关闭该窗口
::SendMessage(hWnd, WM_CLOSE, 0, 0);

posted @ 2009-06-06 18:30 wrh 阅读(2663) | 评论 (1)编辑 收藏
译者:徐景周(原作:Alexander Mikula)

下载本文示例代码

想要通过ODBC直接读、写Excel表格文件,首先,应确保ODBC中已安装有Excel表格文件的驱动"MICROSOFT EXCEL DRIVER (*.XLS)"。然后,可根据下面步骤进行:

1. 在StdAfx.h文件中加入

#include <afxdb.h>
#include <odbcinst.h>
2. 通过ODBC直接创建Excel文件并在表中插入数据(暂定文件名:Demo.xls)
//创建并写入Excel文件
void CRWExcel::WriteToExcel()
{
CDatabase database;
CString sDriver = "MICROSOFT EXCEL DRIVER (*.XLS)"; // Excel安装驱动
CString sExcelFile = "c:\\demo.xls";                // 要建立的Excel文件
CString sSql;
TRY
{
// 创建进行存取的字符串
sSql.Format("DRIVER={%s};DSN='''';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s",
sDriver, sExcelFile, sExcelFile);
// 创建数据库 (既Excel表格文件)
if( database.OpenEx(sSql,CDatabase::noOdbcDialog) )
{
// 创建表结构(姓名、年龄)
sSql = "CREATE TABLE demo (Name TEXT,Age NUMBER)";
database.ExecuteSQL(sSql);
// 插入数值
sSql = "INSERT INTO demo (Name,Age) VALUES (''徐景周'',26)";
database.ExecuteSQL(sSql);
sSql = "INSERT INTO demo (Name,Age) VALUES (''徐志慧'',22)";
database.ExecuteSQL(sSql);
sSql = "INSERT INTO demo (Name,Age) VALUES (''郭徽'',27)";
database.ExecuteSQL(sSql);
}
// 关闭数据库
database.Close();
}
CATCH_ALL(e)
{
TRACE1("Excel驱动没有安装: %s",sDriver);
}
END_CATCH_ALL;
}
3. 通过ODBC直接读取Excel文件(暂定文件名:Demo.xls)
// 读取Excel文件
void CRWExcel::ReadFromExcel()
{
CDatabase database;
CString sSql;
CString sItem1, sItem2;
CString sDriver;
CString sDsn;
CString sFile = "Demo.xls"; 			// 将被读取的Excel文件名
// 检索是否安装有Excel驱动 "Microsoft Excel Driver (*.xls)"
sDriver = GetExcelDriver();
if (sDriver.IsEmpty())
{
// 没有发现Excel驱动
AfxMessageBox("没有安装Excel驱动!");
return;
}
// 创建进行存取的字符串
sDsn.Format("ODBC;DRIVER={%s};DSN='''';DBQ=%s", sDriver, sFile);
TRY
{
// 打开数据库(既Excel文件)
database.Open(NULL, false, false, sDsn);
CRecordset recset(&database);
// 设置读取的查询语句.
sSql = "SELECT Name, Age "
"FROM demo "
"ORDER BY Name ";
// 执行查询语句
recset.Open(CRecordset::forwardOnly, sSql, CRecordset::readOnly);
// 获取查询结果
while (!recset.IsEOF())
{
//读取Excel内部数值
recset.GetFieldValue("Name ", sItem1);
recset.GetFieldValue("Age", sItem2);
// 移到下一行
recset.MoveNext();
}
// 关闭数据库
database.Close();
}
CATCH(CDBException, e)
{
// 数据库操作产生异常时...
AfxMessageBox("数据库错误: " + e->m_strError);
}
END_CATCH;
}
4. 获取ODBC中Excel驱动的函数
CString CRWExcel::GetExcelDriver()
{
char szBuf[2001];
WORD cbBufMax = 2000;
WORD cbBufOut;
char *pszBuf = szBuf;
CString sDriver;
// 获取已安装驱动的名称(涵数在odbcinst.h里)
if (!SQLGetInstalledDrivers(szBuf, cbBufMax, &cbBufOut))
return "";
// 检索已安装的驱动是否有Excel...
do
{
if (strstr(pszBuf, "Excel") != 0)
{
//发现 !
sDriver = CString(pszBuf);
break;
}
pszBuf = strchr(pszBuf, ''\0'') + 1;
}
while (pszBuf[1] != ''\0'');
return sDriver;
}
作者信息:
姓名:徐景周(未来工作室 Future Studio)
EMAIL:jingzhou_xu@163.net

posted @ 2009-05-22 09:22 wrh 阅读(1222) | 评论 (0)编辑 收藏

1.CString::IsEmpty

BOOL IsEmpty( ) const;

返回值:如果CString 对象的长度为0,则返回非零值;否则返回0。

说明:此成员函数用来测试一个CString 对象是否是空的。

示例:

下面的例子说明了如何使用CString::IsEmpty。

// CString::IsEmpty 示例

CString s;

ASSERT( s.IsEmpty() );

请参阅 CString::GetLength

 

2.CString::Left

CString Left( int nCount ) const; 

throw( CMemoryException );

返回值:返回的字符串是前nCount个字符。

示例:

CString s( _T("abcdef") );

ASSERT( s.Left(2) == _T("ab") );

 

3.CString::LoadString

BOOL LoadString( UINT nID );

throw( CMemoryException );

返回值:如果加载资源成功则返回非零值;否则返回0。

nID  一个Windows 字符串资源ID。

说明: 此成员函数用来读取一个由nID 标识的Windows 字符串资源,并放入一个已有CString 对象中。

示例:

下面的例子说明了如何使用CString::LoadString。

// CString::LoadString 示例

#define IDS_FILENOTFOUND 1

CString s;

if (! s.LoadString( IDS_FILENOTFOUND ))

 

4.CString::MakeLower

void MakeLower( );  //改变字符的小写

 

5.CString::MakeReverse

void MakeReverse( );  //字符倒置

 

6.CString::MakeUpper

void MakeUpper( );  //改变字符的大写

 

7.CString::Mid CString Mid( int nFirst ) const; CString Mid( int nFirst, int nCount ) const; nCount代表要提取的字符数, nFirst代表要提取的开始索引位置

示例: CString s( _T("abcdef") ); ASSERT( s.Mid( 2, 3 ) == _T("cde") );

 

8.CString::ReleaseBuffer

void ReleaseBuffer( int nNewLength = -1 );

参数:nNewLength

此字符串的以字符数表示的新长度,不计算结尾的空字符。如果这个字

符串是以空字符结尾的,则参数的缺省值-1 将把CString 的大小设置为

字符串的当前长度。

说明:

使用ReleaseBuffer 来结束对由GetBuffer 分配的缓冲区的使用。如果你知道缓

冲区中的字符串是以空字符结尾的,则可以省略nNewLength 参数。如果字符

串不是以空字符结尾的,则可以使用nNewLength 指定字符串的长度。在调用

ReleaseBuffer 或其它CString 操作之后,由GetBuffer 返回的地址是无效的。

示例:

下面的例子说明了如何使用CString::ReleaseBuffer。

// CString::ReleaseBuffer 示例

CString s;

s = "abc";

LPTSTR p = s.GetBuffer( 1024 );

strcpy(p, "abc"); // 直接使用该缓冲区

ASSERT( s.GetLength() == 3 ); // 字符串长度 = 3

s.ReleaseBuffer(); // 释放多余的内存,现在p 无效。

ASSERT( s.GetLength() == 3 ); // 长度仍然是3

 

9.CString::Remove

int CString::Remove ( TCHAR ch );

返回值:返回从字符串中移走的字符数。如果字符串没有改变则返回零。

参数:ch  要从一个字符串中移走的字符。

说明:此成员函数用来将ch 实例从字符串中移走。与这个字符的比较是区分大小写

的。

示例:

// 从一个句子中移走小写字母'c':

CString str (“This is a test.”);

int n = str.Remove( 't' );

ASSERT( n == 2 );

ASSERT( str ==“This is a es. ” );

 10.CString::Replace

int Replace( TCHAR chOld, TCHAR chNew );

int Replace( LPCTSTR lpszOld, LPCTSTR lpszNew );

返回值:返回被替换的字符数。如果这个字符串没有改变则返回零。

参数:chOld     要被chNew 替换的字符。

chNew    要用来替换chOld 的字符。

lpszOld   一个指向字符串的指针,该字符串包含了要被lpszNew 替换的字符。

LpszNew  一个指向字符串的指针,该字符串包含了要用来替换lpszOld 的字符。

说明:此成员函数用一个字符替换另一个字符。函数的第一个原形在字符串中用chNew

现场替换chOld。函数的第二个原形用lpszNew 指定的字符串替换lpszOld 指定

的子串。

在替换之后,该字符串有可能增长或缩短;那是因为lpszNew 和lpszOld 的长度

不需要是相等的。两种版本形式都进行区分大小写的匹配。

示例:

// 第一个例子,old 和new 具有相同的长度。

CString strZap( “C - -” );

int n = strZap.Replace('-', '+' );

ASSERT( n == 2 );

ASSERT(strZap == “C++” );

// 第二个例子,old 和new 具有不同的长度。

CString strBang( “Everybody likes ice hockey” );

n = strBang.Replace( “hockey”, “golf” );

ASSERT( n ==1 );

n = strBang.Replace ( “likes” , “plays” );

ASSERT( n == 1 );

n = strBang.Replace( “ice”, NULL );

ASSERT( n == 1 );

ASSERT( strBang == “Everybody plays golg” );

// 注意,现在在你的句子中有了一个额外的空格。

// 要移走这个额外的空格,可以将它包括在要被替换的字符串中,例如,“ice ”。

 

11.CString::ReverseFind

int ReverseFind( TCHAR ch ) const;

返回值: 返回此CString 对象中与要求的字符匹配的最后一个字符的索引;如果没有找

到需要的字符则返回-1。

参数: ch  要搜索的字符。

说明:此成员函数在此CString 对象中搜索与一个子串匹配的最后一个字符。此函数

类似于运行时函数strrchr。

示例:

// CString::ReverseFind 示例

CString s( "abcabc" );

ASSERT( s.ReverseFind( 'b' ) == 4 );

 

12.CString::Right

CString Right( int nCount ) const; 

throw( CMemoryException );

返回值: 返回的字符串是最后nCount个字符。

CString s( _T("abcdef") );

ASSERT( s.Right(2) == _T("ef") );

 

13.CString:: SetAt

void SetAt( int nIndex, TCHAR ch );

 说明:可以把字符串理解为一个数组,SetAt类似于[].注意nIndex的范围,如果不合适会有调试错误。 Ch 更替字符, 把nIndex位置上的字符 变成ch

 示例:

CString s( "abc" );

s.MakeReverse();

ASSERT( s == "cba" );

 

14.CString::TrimLeft

void TrimLeft( );

void CString::TrimLeft( TCHAR chTarget );

说明:如果没有参数,从左删除字符(\n\t空格等),至到遇到一个非此类字符. 当然你也可以指定删除那些字符. 如果指定的参数是字符串,那么遇上其中的一个字符就删除. \n  换行符 \t  TAB字符

示例1: CString str = "\n\t a";

str.TrimLeft();

str为“a”;

 示例2:

CString str = "abbcadbabcadb ";

str.TrimLeft("ab");

结果"cadbabcadb "

str.TrimLeft("ac");

结果"bcadbabcadb "

 

15.CString::TrimRight

void TrimRight( );

void CString::TrimRight( TCHAR chTarget );

void CString::TrimRight( LPCTSTR lpszTargets );

说明:用法类似于上面。

 

16.CString::Compare

int Compare( LPCTSTR lpsz ) const;

返回值:字符串一样返回0,小于lpsz  返回-1,大于lpsz  返回1, 区分大小字符

示例:

CString s1( "abc" );

CString s2( "abd" );

ASSERT( s1.Compare( s2 ) == -1 );

ASSERT( s1.Compare( "abe" ) == -1 

17.CString::CompareNoCase

int CompareNoCase( LPCTSTR lpsz ) const;

返回值: 字符串一样 返回0,小于lpsz  返回-1,大于lpsz  返回1,不区分大小字符

 

18.CString::Collate

int Collate( LPCTSTR lpsz ) const;

同CString::Compare

 

19.CString::CollateNoCase

int CollateNocase( LPCTSTR lpsz ) const;

同CString::CompareNoCase

 

20.CString::CString      //构造函数

CString( );

CString( const CString& stringSrc ); 

CString( TCHAR ch, int nRepeat = 1 ); 

CString( LPCTSTR lpch, int nLength );

CString( const unsigned char* psz ); 

CString( LPCWSTR lpsz );

CString( LPCSTR lpsz );

示例:

CString s1;                     

CString s2( "cat" );              

CString s3 = s2;                 

CString s4( s2 + " " + s3 );        

CString s5( 'x' );                      // s5 = "x"

CString s6( 'x', 6 );                   // s6 = "xxxxxx"

CString s7((LPCSTR)ID_FILE_NEW);        // s7 = "Create a new document"

CString city = "Philadelphia";

 

21.CString::Delete

int Delete( int nIndex, int nCount = 1); 

返回值:是被删除前的字符串的长度

nIndex是第一个被删除的字符,nCount是一次删除几个字符。根据我实验得出的结果:当nCount>要删除字符串的最大长度(GetCount() - nIndex)时会出错,当nCount过大,没有足够的字符删除时,此函数不执行。

示例:

CString str1,str2,str3;

char a;

str1 = "nihao";

str2 = "nIhao";

int x;

// int i=(str1 == str2);      

str1.Delete(2,3);

如果nCount(3) > GetCount() – nIndex (5-2)就会执行错误

 

22.CString::Empty

Void Empty( );

返回值:没有返回值  清空操作;

示例:

CString s( "abc" );

s.Empty();

ASSERT( s.GetLength( ) == 0 );

 

23.CString::Find

int Find( TCHAR ch ) const;

int Find( LPCTSTR lpszSub ) const;

int Find( TCHAR ch, int nStart ) const;

int Find( LPCTSTR lpszSub, int nStart ) const;

返回值:  不匹配的话返回 -1;  索引以0 开始; nStar 代表以索引值nStart 的字符开始搜索 ,

即为包含以索引nStart字符后的字符串.

示例:

CString s( "abcdef" );

ASSERT( s.Find( 'c' ) == 2 );

ASSERT( s.Find( "de" ) == 3 );

Cstring str(“The stars are aligned”);

Ing n = str.Find('e',5);

ASSERT(n == 12)

 

24.CString::FindOneOf

int FindOneOf( LPCTSTR lpszCharSet ) const;

返回值:  不匹配的话返回 -1;  索引以0 开始

注意::返回此字符串中第一个在lpszCharSet中也包括字符并且从零开始的索引值

示例:

CString s( "abcdef" );

ASSERT( s.FindOneOf( "xd" ) == 3 ); // 'd' is first match.

 

25.CString::Format

void Format( LPCTSTR lpszFormat, ... );

void Format( UINT nFormatID, ... );

参数:lpszFormat  一个格式控制字符串

nFormatID  字符串标识符

示例:

CString str;

Str.Format(“%d”,13); 

此时Str为13

 

26.CString::GetAt

TCHAR GetAt( int nIndex ) const;

返回值:返回标号为nIndex的字符,你可以把字符串理解为一个数组,GetAt类似于[].注意nIndex的范围,如果不合适会有调试错误。

 

27.CString::GetBuffer

LPTSTR GetBuffer( int nMinBufLength );

返回值:一个指向对象的(以空字符结尾的)字符缓冲区的LPTSTR 指针。

参数:nMinBufLength

字符缓冲区的以字符数表示的最小容量。这个值不包括一个结尾的空字符的空间。

说明:此成员函数返回一个指向CString 对象的内部字符缓冲区的指针。返回的LPTSTR 不是const,因此可以允许直接修改CString 的内容。如果你使用由GetBuffer 返回的指针来改变字符串的内容,你必须在使用其它的CString 成员函数之前调用ReleaseBuffer 函数。

在调用ReleaseBuffer 之后,由GetBuffer 返回的地址也许就无效了,因为其它的CString 操作可能会导致CString 缓冲区被重新分配。如果你没有改变此CString 的长度,则缓冲区不会被重新分配。当此CString 对象被销毁时,其缓冲区内存将被自动释放。

注意:如果你自己知道字符串的长度,则你不应该添加结尾的空字符。但是,当你用ReleaseBuffer 来释放该缓冲区时,你必须指定最后的字符串长度。如果你添加了结尾的空字符,你应该给ReleaseBuffer 的长度参数传递-1 ,ReleaseBuffer 将对该缓冲区执行strlen 来确定它的长度。

示例:

// CString::GetBuffer 例子

CString s( "abcd" );

#ifdef _DEBUG

afxDump << "CString s " << s << "\n";

#endif

LPTSTR p = s.GetBuffer( 10 );

strcpy( p, "Hello" ); // 直接访问CString 对象。

s.ReleaseBuffer( );

#ifdef _DEBUG

afxDump << "CString s " << s << "\n";

#endif

 

28.CString::GetLength

int GetLength( ) const;

返回值:返回字符串中的字节计数。

说明:此成员函数用来获取这个CString 对象中的字节计数。这个计数不包括结尾的空字符。

对于多字节字符集(MBCS),GetLength 按每一个8 位字符计数;即,在一个多字节字符中的开始和结尾字节被算作两个字节。

示例

下面的例子说明了如何使用CString::GetLength。

// CString::GetLength 示例

CString s( "abcdef" );

ASSERT( s.GetLength() == 6 );

 

29.CString::Insert

int Insert( int nIndex, TCHAR ch ); 

int Insert( int nIndex, LPCTSTR pstr );

返回值:返回修改后的长度,nIndex是字符(或字符串)插入后的索引号例子

示例:

CString str( “HockeyBest”);

 int n = str.Insert( 6, “is” );

 ASSERT( n == str.GetLength( ) ); 

printf( “1: %s\n”, ( LPCTSTR ) str );

 n = str.Insert( 6, ' ' ); 

ASSERT( n == str.GetLength( ) ); 

printf ( “2: %s\n”, (LPCTSTR) STR );

 n = str.Insert(555, ‘1’);

ASSERT( n == str.GetLength ( ) );

 printf ( “3: %s\n”, ( LPCTSTR ) str );

输出

1. Hockeyis Best

2. Hockey is Best

3. Hockey is Best!

posted @ 2009-05-22 09:19 wrh 阅读(48057) | 评论 (0)编辑 收藏
在开发软件的过程里,经常需要把数据保存到当前执行文件路径下面,或者读取当前执行文件路径下的一些配置信息。这时就需要从当前模块里获取所在的目录路径,以便进行固定的位置操作文件。要解决这个需求,就需要调用API函数GetModuleFileName来获取模块所在的路径。

函数GetModuleFileName声明如下:
WINBASEAPI
DWORD
WINAPI
GetModuleFileNameA(
    __in_opt HMODULE hModule,
    __out_ecount_part(nSize, return + 1) LPCH lpFilename,
    __in    DWORD nSize
    );
WINBASEAPI
DWORD
WINAPI
GetModuleFileNameW(
    __in_opt HMODULE hModule,
    __out_ecount_part(nSize, return + 1) LPWCH lpFilename,
    __in    DWORD nSize
    );
#ifdef UNICODE
#define GetModuleFileName GetModuleFileNameW
#else
#define GetModuleFileName GetModuleFileNameA
#endif // !UNICODE
hModule是模块的句柄,或者设置为NULL表示当前模块。
lpFilename是保存路径的缓冲区。
nSize是缓冲区的大小。

调用函数的例子如下:
#001 //获取当前程序所在路径。
#002  //蔡军生 2007/12/05 QQ:9073204 深圳
#003  void TestGetExePath(void)
#004  {
#005        //
#006        const int nBufSize = 512;
#007        TCHAR chBuf[nBufSize];
#008        ZeroMemory(chBuf,nBufSize);
#009
#010        //获取当前执行文件的路径。
#011        if (GetModuleFileName(NULL,chBuf,nBufSize))
#012        {
#013              //输出带文件名称路径。
#014              OutputDebugString(chBuf);
#015              OutputDebugString(_T("\r\n"));
#016
#017              //获取文件路径。
#018              TCHAR* lpStrPath = chBuf;
#019              PathRemoveFileSpec(lpStrPath);
#020              OutputDebugString(lpStrPath);
#021              OutputDebugString(_T("\r\n"));
#022        }
#023
#024  }

输出的结果如下:
g:\work\windows_api\wincpp2\debug\WinCpp.exe
g:\work\windows_api\wincpp2\debug
posted @ 2009-05-22 08:36 wrh 阅读(439) | 评论 (0)编辑 收藏
GetModuleFileName是获得程序当前的运行目录
GetCurrentDirectory获取当前进程所有在的目录

复制代码
  1.  CFileDialog fdlg(true);
  2.  fdlg.DoModal();//////
  3.  TCHAR *pBuffer = new TCHAR[1024];
  4.  ZeroMemory(pBuffer, 1024);
  5.  GetCurrentDirectory(1024, pBuffer);
  6.  MessageBox(pBuffer, L"GetCurrentDirectory");
  7.  ZeroMemory(pBuffer, 1024);
  8.  GetModuleFileName(NULL, pBuffer, 1024);
  9.  MessageBox(pBuffer, L"GetModuleFileName");

posted @ 2009-05-22 08:26 wrh 阅读(845) | 评论 (0)编辑 收藏

下载本文示例代码

想要通过ODBC直接读、写Excel表格文件,首先,应确保ODBC中已安装有Excel表格文件的驱动"MICROSOFT EXCEL DRIVER (*.XLS)"。然后,可根据下面步骤进行:

1. 在StdAfx.h文件中加入:
#include <afxdb.h>

#include <odbcinst.h>

2. 通过ODBC直接创建Excel文件并在表中插入数据(暂定文件名:Demo.xls)
//创建并写入Excel文件

void CRWExcel::WriteToExcel()

{

  CDatabase database;

  CString sDriver = "MICROSOFT EXCEL DRIVER (*.XLS)"; // Excel安装驱动

  CString sExcelFile = "c:\\demo.xls";                // 要建立的Excel文件

  CString sSql;

   

  TRY

  {

    // 创建进行存取的字符串

    sSql.Format("DRIVER={%s};DSN='''';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s",

                sDriver, sExcelFile, sExcelFile);

 

    // 创建数据库 (既Excel表格文件)

    if( database.OpenEx(sSql,CDatabase::noOdbcDialog) )

    {

      // 创建表结构(姓名、年龄)

      sSql = "CREATE TABLE demo (Name TEXT,Age NUMBER)";

      database.ExecuteSQL(sSql);

 

      // 插入数值

      sSql = "INSERT INTO demo (Name,Age) VALUES (''徐景周'',26)";

      database.ExecuteSQL(sSql);

 

      sSql = "INSERT INTO demo (Name,Age) VALUES (''徐志慧'',22)";

      database.ExecuteSQL(sSql);

 

      sSql = "INSERT INTO demo (Name,Age) VALUES (''郭徽'',27)";

      database.ExecuteSQL(sSql);

    }     

 

    // 关闭数据库

    database.Close();

  }

  CATCH_ALL(e)

  {

    TRACE1("Excel驱动没有安装: %s",sDriver);

  }

  END_CATCH_ALL;

}

3. 通过ODBC直接读取Excel文件(暂定文件名:Demo.xls)
// 读取Excel文件

void CRWExcel::ReadFromExcel()

{

    CDatabase database;

    CString sSql;

    CString sItem1, sItem2;

    CString sDriver;

    CString sDsn;

    CString sFile = "Demo.xls";    // 将被读取的Excel文件名

                                    

    // 检索是否安装有Excel驱动 "Microsoft Excel Driver (*.xls)"

    sDriver = GetExcelDriver();

    if (sDriver.IsEmpty())

    {

        // 没有发现Excel驱动

        AfxMessageBox("没有安装Excel驱动!");

        return;

    }

   

    // 创建进行存取的字符串

    sDsn.Format("ODBC;DRIVER={%s};DSN='''';DBQ=%s", sDriver, sFile);

 

    TRY

    {

        // 打开数据库(既Excel文件)

        database.Open(NULL, false, false, sDsn);

       

        CRecordset recset(&database);

 

        // 设置读取的查询语句.

        sSql = "SELECT Name, Age "      

               "FROM demo "                

               "ORDER BY Name ";

   

        // 执行查询语句

        recset.Open(CRecordset::forwardOnly, sSql, CRecordset::readOnly);

 

        // 获取查询结果

        while (!recset.IsEOF())

        {

            //读取Excel内部数值

            recset.GetFieldValue("Name ", sItem1);

            recset.GetFieldValue("Age", sItem2);

 

            // 移到下一行

            recset.MoveNext();

        }

 

        // 关闭数据库

        database.Close();

                            

    }

    CATCH(CDBException, e)

    {

        // 数据库操作产生异常时...

        AfxMessageBox("数据库错误: " + e->m_strError);

    }

    END_CATCH;

}

4. 获取ODBC中Excel驱动的函数
CString CRWExcel::GetExcelDriver()

{

    char szBuf[2001];

    WORD cbBufMax = 2000;

    WORD cbBufOut;

    char *pszBuf = szBuf;

    CString sDriver;

 

    // 获取已安装驱动的名称(涵数在odbcinst.h里)

    if (!SQLGetInstalledDrivers(szBuf, cbBufMax, &cbBufOut))

        return "";

   

    // 检索已安装的驱动是否有Excel...

    do

    {

        if (strstr(pszBuf, "Excel") != 0)

        {

            //发现 !

            sDriver = CString(pszBuf);

            break;

        }

        pszBuf = strchr(pszBuf, ''\0'') + 1;

    }

    while (pszBuf[1] != ''\0'');

 

    return sDriver;

}

作者信息:
姓名:徐景周(未来工作室 Future Studio)
EMAIL:jingzhou_xu@163.net

本文来自: 乘风原创程序(http://www.qqcf.com) 详细出处参考:http://study.qqcf.com/web/197/22219.htm

posted @ 2009-05-21 21:25 wrh 阅读(839) | 评论 (0)编辑 收藏

一、 VC 提供的数据库访问技术

ODBC API MFC ODBC DAO OLE DB ADO

访问速度:传统的 ODBC 速度较慢。 OLE DB ADO 都是基于 COM 技术,使用该技术可以直接访问数据库的驱动程序,速度大大提高。

 

可扩展性:通过 OLE DB ActiveX 技术,可以利用 VC 提供的各种组件,控件和第三方提供的组建。从而实现应用程序组件化。

 

访问不同数据源:传统 ODBC 只能访问关系数据库。 VC 中提供 OLD DB 技术可以解决该问题。

二、 几种技术概述

1、 ODBC API

提供一个通用接口,为 ORACLE SQLSERVER 都提供了驱动程序。用户可以 SQL 语句对数据库进行直接的底层功能操作。使用时应包含以下头文件。 ”SQL.H”,”SQLEXT.H”,”SQLTYPES.H”.

使用步骤如下:

第一步:分配 ODBC 环境,初始化一些内部结构。完成该步,需要分配一个 SQLHENV 类型的变量在 ODBC 环境中做句柄使用。

第二步:为将要使用的每一个数据源分配一个连接句柄,有函数 SQLALLocHandle ()完成。

第三步:使用 SQLConnect ()把连接句柄与数据库连接,可以先通过 SQLSetConnectAttr ()设置连接属性。

第四步:进行 SQL 语句操作。操作完就可以断开与数据库的连接。

第五步:释放 ODBC 环境。

 

特点:功能强大,提供异步操作,事务处理等高级功能。目前所有关系数据库都提供了 ODBC 的驱动程序,使用很广泛。

缺点:很难访问对象数据库和非关系数据库。

 

2、 MFC ODBC

 

为简化使用 ODBC API VC 提供了 MFC ODBC 类,封装了 ODBC API

主要 MFC ODBC 类如下:

CDatabase 类:一个 CDatabase 对象表示一个到数据源的连接,通过它可以操作数据源。一般不需要直接使用 CDatabase 对象,因为 CDecordSet 对象可以实现大多数功能,但在进行事务处理时, CDatabase 就起到关键作用。

CRecordSet 类:一个 CRecordSet 对象代表一个从数据源选择的一组记录的集合 ----- 记录集。记录集有两种形式: snapshot dynaset 。前者表示是静态视图。后者表示记录集与其它用户对数据库的更新保持同步。

CRecordView 类:是在空间中显示数据库记录的视图。这种视图是直接连到一个 CRecordSet 对象的格式视图。他从一个对话框模版资源创建。并将 CRecordSet 对象的字段显示在对话框模版的控件里。对象利用 DDX RFX 机制。使格式上的控件和记录集的字段之间数据移动自动化。

CDBException 类:由 Cexception 类派生,以 3 个继承的变量反映对数据库操作时的异常。

 M_nRetCode: ODBC 返回码。

M_strError: 字符串,描述造成抛出异常的错误原因。

M_strStateNativeOrigin: 字符串,描述以 ODBC 错误码表示的异常错误。

 

3、 MFC DAO

 

MFC DAO 是微软提供的用于访问 Microsoft Jet 数据库文件( * Mdb )的工具。当只需访问 Access 数据库时用该技术很方便。

4、 OLE DB

 

ODBC 技术类似, OLE DB 属于数据库访问技术中的底层接口。

直接使用 OLEDB 需要大量代码, VC 中提供了 ATL 模版,

OLEDB 框架定义了应用的 3 个基本类。

 

数据提供程序 Data Provider 拥有自己的数据并以表格形式显示数据的应用程序。

使用者 Consumers :试用 OLEDB 接口对存储在数据提供程序中对数据进行控制的应用程序。

服务提供程序 ServiceProvider :是数据提供程序和使用者的组合。

 

使用 OLE DB 编程时,用户使用组件对象开发程序,这些组件包括:

枚举器:用于列出可用的数据源;

数据源:代表单独的数据和服务提供程序,用于创建对话;

对话:     用于创建事务和命令;

事务:     用于将多个操作归并为单一事务处理;

命令:     用于向数据源发送文本命令( SQL ),返回行集;

错误:     用于获得错误信息。

5、 ADO

 

ADO 技术是基于 OLE DB 的访问接口。继承了 OLEDB 的优点,并对 OLEDB 的接口作了封装,定义了 ADO 对象,使开发简化。 ADO 属于数据库访问的高层接口。

 

ADO 在服务器应用方面非常有效,特别是动态服务器页面( ASP )的支持。

 

ADO 对象结构类似于 OLEDB ,但并不依靠对象层次。大多数情况用户只需创建并使用需要的对象。下面的对象类组成了 ADO 接口。

 

Connection  用于表示与数据库的连接,以及处理一些事务和命令。

Command    用于处理传送给数据源的命令。

Recordset    用于处理数据的表格集, 包括获取和修改数据。

Field            用于表示记录集中的列信息,包括列值和其他信息。

Parameter    在传送给数据源的命令之间传递数据。

Property      用于操作在 ADO 中使用的其它对象的详细属性。

Errro           用于获取可能发生的详细错误信息

posted @ 2009-05-21 21:18 wrh 阅读(376) | 评论 (0)编辑 收藏
使用VC编程来操纵Office。你可以实现诸如:Word文件打印、传送数据到Word文档、发送E-MAIL、自动产生表格、Excel数据统计、圆饼图,直方图显示、自动报表生成、播放幻灯、doc,txt,HTML,rtf文件转换、中文简繁体转换、拼音或笔画排序......只要是Office能够实现的功能,都可以在你写的程序中调用。仔细阅读下面的说明,并下载源文件进行参考,你就可以一步一步地掌握这个技术。祝朋友们学习快乐。

  一、概念

  Microsoft 的 Office 产品中,都提供了OLE Automation 自动化程序的接口。如果你使用VB,VBA 和 Script 脚本调用 Office 功能的话,其实比使用 VC 调用要简单的多。比如在 WORD 中,调出菜单“工具(T)\宏(M)\录制新宏(R)”,这时候它开始记录你在 WORD 中任何菜单和键盘的操作,把你的操作过程保存起来,以便再次重复调用。而保存这些操作的记录,其实就是使用了 VBA 程序(Visual Basic for Application)。而我们下面要实现的功能,也同样要参考 VBA 的方法。

  二、结构层次

  为了更有逻辑,更有层次地操作 Office,Microsoft 把应用(Application)按逻辑功能划分为如下的树形结构

Application(WORD 为例,只列出一部分)
Documents(所有的文档)
Document(一个文档)
......
  Templates(所有模板)
Template(一个模板)
......
  Windows(所有窗口)
Window
Selection
View
Selection(编辑对象)
Font
Style
Range
......
......

  只有了解了逻辑层次,我们才能正确的操纵 Office。举例来讲,如果给出一个VBScript语句是:
application.ActiveDocument.SaveAs "c:\abc.doc"

  那么,我们就知道了,这个操作的过程是:第一步,取得Application;第二步,从Application中取得ActiveDocument;第三步,调用 Document 的函数 SaveAs,参数是一个字符串型的文件名。
三、基本步骤

  (1)创建(或打开已有的)一个 MFC 的程序工程

  (2)Ctrl+W 执行 ClassWizard(本文按照 VC6 操作,例子程序也是在VC6 下编写测试的)

  (3)Add Class...\From a type Library... 在 Office 目录中,找到你想使用的类型库。(我使用的是 Office2000,其Word 的类型库文件,保存在 C:\Program Files\Microsoft Office\Office\MSWORD9.OLB)根据你 Office 的版本,可以使用下表列出的类型库文件

Office 版本和类型 类型库文件 Office 版本和类型 类型库文件
Access 97 Msacc8.olb PowerPoint 2000 Msppt9.olb
Jet Database 3.5 DAO350.dll Word 2000 Msword9.olb
Binder 97 Msbdr8.olb Access 2002 Msacc.olb
Excel 97 Excel8.olb Excel 2002 Excel.exe
Graph 97 Graph8.olb Graph 2002 Graph.exe
Office 97 Mso97.dll Office 2002 MSO.dll
Outlook 97 Msoutl97.olb Outlook 2002 MSOutl.olb
PowerPoint 97 Msppt8.olb PowerPoint 2002 MSPpt.olb
Word 97 Msword8.olb Word 2002 MSWord.olb
Access 2000 Msacc9.olb Office Access 2003 Msacc.olb
Jet Database 3.51 DAO360.dll Office Excel 2003 Excel.exe
Binder 2000 Msbdr9.olb Graph 2003 Graph.exe
Excel 2000 Excel9.olb Office 2003 MSO.dll
Graph 2000 Graph9.olb Office Outlook 2003 MSOutl.olb
Office 2000 Mso9.dll Office PowerPoint 2003 MSPpt.olb
Outlook 2000 Msoutl9.olb Office Word 2003 MSWord.olb

  (4)选择类型库文件后,在弹出的对话窗中继续选择要添加的类。具体选择什么类,要看你将来在程序中打算调用什么功能。当然,你也可以不用考虑这么多,用鼠标和Shift键配合,全部选择也可以。

  (5)初始化COM。方法一,找到App的InitInstance()函数,在其中添加 AfxOleInit()函数的调用;方法二,在需要调用COM功能的地方 CoInitialize(NULL),调用完毕后 CoUninitialize()。

  (6)在你需要调用 Office 功能函数的 cpp 文件中

#include <atlbase.h> // 为了方便操作 VARIANT 类型变量,使用 CComVariant 模板类
#include "头文件.h"
// 具体的头文件名,是由装载类型库的文件名决定的。(鼠标双点包装类的文件,就可以看到)
// 比如使用 msword9.olb类型库,那么头文件是 msword9.h

  (7)好了,现在开始写程序吧。另外要说明的是,步骤3和4,其实也可以使用 #import 方式引入类型库。

  四、实现技巧

  在书写调用 Office 函数的过程中,最困难的是确定函数的参数,一般情况下,参数都是 VARIANT 类型的变量指针。那么到底具体我们应该怎么写那?推荐两个方法,其一是阅读有关 VBA 的书籍;其二,是使用 Office 中自带的“宏”功能。强烈推荐大家使用第二个方法,把你要完成的功能,在 Office 的操作环境中,用宏录制下来,然后观察分析录制后的函数和参数,就可以在 VC 中使用了。举一个例子:

ActiveDocument.SaveAs FileName:="Hello.doc", FileFormat:=wdFormatDocument _
, LockComments:=False, Password:="", AddToRecentFiles:=True, _
WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
False

  以上是在 Word 中录制的一个保存文件的宏,而在 VC 中对应的函数原型为 void _Document::SaveAs(VARIANT* FileName, VARIANT* FileFormat, VARIANT* LockComments,
VARIANT* Password, VARIANT* AddToRecentFiles, VARIANT* WritePassword,
VARIANT* ReadOnlyRecommended, VARIANT* EmbedTrueTypeFonts, VARIANT* SaveNativePictureFormat,
VARIANT* SaveFormsData, VARIANT* SaveAsAOCELetter)

  分析对照后,我们就能看出,参数 FileName 是字符串 VARIANT(VT_BSTR),参数 LockComments 是布尔VARIANT(VT_BOOL),等等。参数 FileFormat := wdFormatDocument 是什么类型那?其实这是一个表示保存的时候指定文件类型的常量,而且显然是 DWORD 类型VARIANT(VT_I4)。那么常量的数值又是多少那?很简单,写一个宏,调用函数 MsgBox 显示一下不就都知道啦?!

  五、步步为营

  特别提示一:编译执行前,一定要先关闭 KV 实时监视病毒的功能(KV 的程序会干扰我们的调用,瑞星的则没关系)。

   特别提示二:在例子程序中,为了表现程序的关键部分,没有或很少使用了条件判断。为了实现你程序的健壮性,请自己加上条件判断和异常处理。

  Step1:如何启动和关闭 WORD,及 VARIANT 的最基本的使用方法
  Step2:和 Step1 同样功能,用 CComVariant 改进了 VARIANT 的使用方式
  Step3:在 Step2 的基础上,新建一个 WORD 文档,并从程序中传送一些字符到 WORD
  Step4:在 Step3 的基础上,保存 WORD 文档
  Step5:一个小应用举例,把输入的汉字按照“笔画”排序
  Step6:一个小应用举例,盗窃正在使用的 WORD 文档

  以上这6个小程序中,都有详细的注释。大家阅读后慢慢体会并实验,你就可以自由地操纵任何一个 Office 啦。

  源代码下载

posted @ 2009-05-21 21:14 wrh 阅读(277) | 评论 (0)编辑 收藏
仅列出标题
共25页: First 12 13 14 15 16 17 18 19 20 Last 

导航

<2011年1月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

统计

常用链接

留言簿(19)

随笔档案

文章档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜