星期一, 九月 03, 2007

API技巧集

API技巧集(一)- -




一、拖动无标题窗体:

包含头文件:

#include $#@60;winuser.h$#@62;

在窗体或组件的 OnMouseDown 事件中加入以下代码:

if(Button == mbLeft)
{
ReleaseCapture();
SendMessage( Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}

二、弹出和关闭光驱:

包含头文件:

#include $#@60;mmsystem.h$#@62;

在窗体的OnCreate事件中加入:

mciSendString("open cdaudio alias cd wait shareable",0,0,0);

1、要弹出光驱时使用:

mciSendString("set cd door open",0,0,0);

2、要关闭光驱时使用:

mciSendString("set cd door closed",0,0,0);

三、提取图标:

包含头文件:

#include $#@60;shellapi.h$#@62;

例子:

TIcon *Icon = new TIcon();
AnsiString FileName = "C:\\WINDOWS\\SYSTEM\\SHELL32.DLL";
int TotalIcon;

//得到文件SHELL32.DLL的总图标数
TotalIcon = (int)ExtractIcon(Form1->Handle,FileName.c_str(), -1);

//提取第一个图标,0为第一个,1为第二个,类推...
Icon->Handle = ExtractIcon( Form1->Handle, FileName.c_str(), 0);

//保存图标
Icon->SaveToFile("C:\\1.ICO");

四、设置顶端窗口(永在上面):

包含头文件:

#include $#@60;winuser.h$#@62;

1、设置顶层窗口

SetWindowPos( Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE||SWP_NOSIZE);

2、取消顶层窗口

SetWindowPos( Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE||SWP_NOSIZE);


API技巧集 (二)

  (一)不规则窗口

  Windows提供的只是标准的矩形窗口,要想建立一个不规则的窗口就需要调用API函数来实现。建立一个不规则的窗口,一般是先用创建区域的API函数建立一个不规则的区域,再用API函数SetWindowRgn改变窗口的区域。这些API函数在C++ Builder中包含在头文件wingdi.h和winuser.h里面,因此,要使用这些API函数就要先在程序头部加上包含头文件的语句:

include $#@60;wingdi.h$#@62;

include $#@60;winuser.h$#@62;

  SetWindowRgn函数能改变一个窗口的区域,该函数有三个参数,第一个参数hWnd是欲设置区域的窗口句柄,第二个参数hRgn是欲设置的区域,第三个参数bRedraw一般设为true,即立即重画窗口。

  用来创建区域的API函数有多个,最常用的有三个:

  1、CreateRectRgn函数,用来创建一个由X1、Y1和X2、Y2坐标点确定的矩形区域。当坐标点X1和Y1相等、X2和Y2也相等的时候,创建的是一个正方形。

  例子:

//创建长方形

HRGN hRect=CreateRectRgn(0,0,400,200);

SetWindowRgn(Handle,hRect,true);

//创建正方形

HRGN hRect=CreateRectRgn(0,0,300,300);

SetWindowRgn(Handle,hRect,true);

  2、CreateEllipticRgn函数,用来创建一个由X1、Y1和X2、Y2坐标点确定的矩形所内切的椭圆。同样,X1、Y1和X2、Y2坐标点所确定的矩形为正方形时,创建的就是一个圆形。

  例子:

//创建椭圆

HRGN hElliptic=CreateEllipticRgn(0,0,400,250);

SetWindowRgn(Handle,hElliptic,true);

//创建圆形

HRGN hElliptic=CreateEllipticRgn(0,0,400,400);

SetWindowRgn(Handle,hElliptic,true);

  3、CombineRgn函数,能将两个区域组合为一个新区域,它有四个参数,第一个参数hrgnDest保存合并后的新区域,第二个参数hrgnSrc1、三个参数hrgnSrc2为欲合并的两个区域,第四个参数fnCombineMode是区域组合的方式,它的值是为下面组合方式之一:

  组合方式 说明

RGN_AND 建立两个区域的交集

RGN_COPY 建立hrgnSrc1的拷贝

RGN_DIFF 建立两个区域不相交的部分

RGN 建立两个区域的并集

RGN_XOR 建立除两个区域并集之外的部分

  例子:

//创建一个圆形和长方形交集的组合形状

HRGN hRect=CreateRectRgn(0,0,300,300);

HRGN hElliptic=CreateEllipticRgn(0,0,400,250);

CombineRgn(hRect,hRect,hElliptic,RGN_OR);

SetWindowRgn(Handle,hRect,true);

  当需要将窗口还原为标准Windows矩形窗口时,只要将SetWindowRgn函数的hRgn参数设为0就行了,如:

SetWindowRgn(Handle,0,true);


API技巧集 (二)



  (二)得到系统声卡的个数

  当我们编写一个多媒体程序(如播放器)的时候,有时需要检测一下计算机中是否安装了声卡,如果没有装声卡程序则会终止运行。

  在这里,我们就要使用API函数waveOutGetNumDevs,调用这个函数可返回系统中安装了的声卡的个数。在C++ Builder 5.0中,它被包含在头文件“mmsystem.h”里面。

  例子:

  1、首先在程序头部加入包含头文件的代码:

#include $#@60;mmsystem.h$#@62;

  2、在窗体的OnCreate事件中加入下面的代码:

int Num;

//得到声卡的个数

Num=waveOutGetNumDevs();

if(Num)

ShowMessage("你有安装了"+IntToStr(Num)+"块声卡");

else

{

ShowMessage("你没有安装声卡!\n程序终止运行!");

Close();

}

  3、编译运行程序。

API技巧集 (二)


  (三)获得、设置鼠标双击的间隔时间

  在指定间隔的时间内,连续两次鼠标单击操作称为双击,双击间隔的时间可以在控制面板中的鼠标属性里面改变。若要在自编的应用程序中能获得或设置鼠标双击的间隔时间,我们只需使用Windows的两个API函数GetDoubleClickTime和SetDoubleClickTime。调用GetDoubleClickTime可以返回鼠标双击的间隔时间,而使用SetDoubleClickTime则可以设置鼠标双击间隔的时间。

  下面让我们来做一个获得和设置鼠标双击间隔时间的简单的程序:

  首先,在Borland C++ Builder 5.0 中新建一个工程,往窗体Form1中添加两个Button组件,把它们的Caption属性分别改为“获取双击间隔时间”和“设置双击间隔时间”,再添加一个Edit组件,将Edit1的Text属性改为“200”,添加一个Label组件,把Caption属性改为“毫秒”。

  然后,双击按钮Button1,在它的OnClick(单击)事件中加入下面的代码:

//返回鼠标双击间隔时间

ShowMessage("鼠标双击间隔时间为"+IntToStr(GetDoubleClickTime())+"毫秒");

  再双击按钮Button2,也在它的OnClick事件中加入代码:

//设置鼠标双击间隔时间

SetDoubleClickTime(StrToInt(Edit1-$#@62;Text));

  最后,按F9编译运行一下程序。点击窗口中的“获取双击间隔时间”按钮就会弹出一个显示当前系统鼠标双击间隔的时间,若要设置鼠标双击间隔的时间,只要改变文本框中的数值,比如300吧,再点击“设置双击间隔时间”按钮就可以了。需要注意的是,鼠标双击间隔时间的单位是毫秒,设置的值越小,间隔的时间就越小,双击的速度就越快,系统默认的是400毫秒,可不要设得太小了,否则“我的电脑”会打不开的(你双击的速度不够快,^_^)。





 API技巧集 (二)



  (四)启动控制面板控制台应用程序

  在控制面板里有许多的控制面板项目,这些项目就是控制台应用程序,它们都是标准的DLL(动态链接库)文件,我们经常需要通过它们来对Windows进行配置。rundll32.exe就是专门用来调用DLL文件的程序,在C++ Builder编程中,我们可以通过使用API函数WinExec运行外部程序rundll32.exe调用DLL来实现启动控制面板的控制台应用程序。下面是收集的一些调用DLL启动控制台应用程序的例子:

  1、打开控制面板  

WinExec("rundll32.exe shell32.dll,Control_RunDLL",SW_SHOWNORMAL);

  2、打开方式对话框

WinExec("rundll32.exe shell32.dll,OpenAs_RunDLL "c:\\autoexec.bat"",SW_SHOWNORMAL);

  3、添加Modem

WinExec("rundll32.exe shell32.dll,Control_RunDLL modem.cpl,,add",SW_SHOWNORMAL);

  4、添加打印机

WinExec("rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL AddPrinter",SW_SHOWNORMAL);

  5、复制磁盘

WinExec("rundll32.exe diskcopy.dll,DiskCopyRunDll",SW_SHOWNORMAL);

  6、鼠标

WinExec("rundll32.exe shell32.dll,Control_RunDLL main.cpl",SW_SHOWNORMAL);

  7、网络

WinExec("rundll32.exe shell32.dll,Control_RunDLL netcpl.cpl",SW_SHOWNORMAL);

  8、密码

WinExec("rundll32.exe shell32.dll,Control_RunDLL password.cpl",SW_SHOWNORMAL);

  9、游戏控制器

WinExec("rundll32.exe shell32.dll,Control_RunDLL joy.cpl",SW_SHOWNORMAL);

  10、日期/时间

WinExec("rundll32.exe shell32.dll,Control_RunDLL timedate.cpl",SW_SHOWNORMAL);

  11、Internet 属性
WinExec("rundll32.exe shell32.dll,Control_RunDLL inetcpl.cpl",SW_SHOWNORMAL);

  12、添加/删除程序

//安装/卸载

WinExec("rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,1",SW_SHOWNORMAL);

//Windows 安装

WinExec("rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,2",SW_SHOWNORMAL);

//启动盘

WinExec("rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,3",SW_SHOWNORMAL);

  13、区域设置

//区域设置

WinExec("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,0",SW_SHOWNORMAL);

//数字

WinExec("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,1",SW_SHOWNORMAL);

//货币

WinExec("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,2",SW_SHOWNORMAL);

//时间

WinExec("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,3",SW_SHOWNORMAL);

//日期

WinExec("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,4",SW_SHOWNORMAL);

  14、辅助选项

//键盘

WinExec("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,1",SW_SHOWNORMAL);

//声音

WinExec("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,2",SW_SHOWNORMAL);

//显示

WinExec("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,3",SW_SHOWNORMAL);

//鼠标

WinExec("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,4",SW_SHOWNORMAL);

//常规

WinExec("rundll32.exe shell32.dll,Control_RunDLL access.cpl,,5",SW_SHOWNORMAL);

  15、多媒体

//音频

WinExec("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,0",SW_SHOWNORMAL);

//视频

WinExec("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,1",SW_SHOWNORMAL);

//MIDI

WinExec("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,2",SW_SHOWNORMAL);

//CD 音乐

WinExec("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,3",SW_SHOWNORMAL);

//设备

WinExec("rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl,,4",SW_SHOWNORMAL);

  16、系统

//常规

WinExec("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,0",SW_SHOWNORMAL);

//设备管理器

WinExec("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,1",SW_SHOWNORMAL);

//硬件配置文件

WinExec("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,2",SW_SHOWNORMAL);

//性能

WinExec("rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,3",SW_SHOWNORMAL);

  17、显示器

//背景

WinExec("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0",SW_SHOWNORMAL);

//屏幕保护

WinExec("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,1",SW_SHOWNORMAL);

//外观

WinExec("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2",SW_SHOWNORMAL);

//设置

WinExec("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,3",SW_SHOWNORMAL);  

  这些例子在Windows 98和Windows 2000中都可以使用通过,前提是在控制面板中安装了该项目。


API技巧集(三)

  (一)闪烁程序的标题栏

  在某些专业的应用程序中,当程序需要提醒用户或要引起用户的注意时,就不停地闪烁程序的标题栏。要实现这个功能,只需要一个Timer组件和使用一个API函数--FlashWindow。

  使用API函数FlashWindow可以闪烁显示指定窗口,让窗口在活动与非活动的状态之间切换,它有两个参数:hwnd和bInvert,头文件为“winuser.h”。其中,参数hwnd为要闪烁的窗口句柄,参数bInvert是一个bool变量,设为true时,程序窗口标题栏从活动切换到非活动状态、或反向切换,当设为false时,窗口标题栏还原为最初的状态。如果配合一个时间组件(Timer组件),以一定的时间间隔执行语句:

FlashWindow(Form1-$#@62;Handle,true);

程序窗口的标题栏就在活动、非活动的状态之间不停地切换。若把hwnd指定成为应用程序的句柄(Application-$#@62;Handel),将会闪烁程序在任务栏上的标题栏。

  下面就让我们来做一个闪烁窗口标题栏和任务栏上标题栏的程序。

  首先,在Form1中添加三个按钮Button1、Button2和Button3,把它们的属性分别为“闪烁窗口标题栏”、“闪烁任务标题栏”和“停止闪烁”,再加入两个时间组件Timer1和Timer2,将两个Timer组件的Enabled属性都设为false,将Interval属性都设为为500(即半秒),改变这个属性的值可以修改闪烁的频率。

  然后,双击Timer1,在OnTimer事件中加入:

FlashWindow(Form1-$#@62;Handle,true);

  双击Timer2,在OnTimer事件中加入:

FlashWindow(Application-$#@62;Handel,true);

  双击Button1,在Button1的OnClick事件中加入:

Timer1-$#@62;Enabled=true;

  双击Button2,在Button2的OnClick事件中加入:

Timer2-$#@62;Enabled=true;

  最后,双击Button3,在Button3的OnClick事件中加入:

Timer1-$#@62;Enabled=false;

Timer2-$#@62;Enabled=false;

FlashWindow(Form1-$#@62;Handle,false);

FlashWindow(Application-$#@62;Handel,false);

  这样,一个简单的例子就完成了。按F9编译运行程序,你就可闪烁窗口标题栏或是闪烁任务栏上? 题栏了。


  (二)拖动无标题窗体

  现在的Windows应用程序,大都使用了图形化的界面、不规则窗口技术,使得程序界面更加漂亮了。但是,使用界面一般要先把窗体的标题栏去掉(在BCB中,将窗体的BorderStyle属性设为bsNone,就可以把窗体的标题栏去掉),这样就不能使用原来的标题栏了,出现了窗口不能移动的问题。没有标题栏怎样用鼠标拖动窗体呢?我们可以使用Windows的API函数SendMessage来解决这个问题。

  首先,新建一个工程,把窗体的BorderStyle属性设为bsNone去掉窗体的标题栏,按F12键切换到代码编辑窗口,在头部加入包含头文件"winuser.h"的代码:

#include $#@60;winuser.h$#@62;

  然后,在窗体的 OnMouseDown 事件中加入下面的代码:

if(Button == mbLeft)//判断是否按了鼠标左键

{

ReleaseCapture();//释放鼠标操作

SendMessage( Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);

}

  这样,用鼠标左键点住窗口拖动,就可以实现拖动没有标题的窗口了。也可以在窗体上添加组件,然后在该组件的 OnMouseDown 事件中加入上面的代码,这样也可以点住这个组件拖动窗口。你还可以把SendMessage函数的第一个参数修改为这个组件的句柄,如:往窗体添加一个Button组件,在它的 OnMouseDown 事件中加入上面的代码,其中把SendMessage那行语句改为:

SendMessage( Button1-$#@62;Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);

这样就可以在程序运行时,用鼠标在窗口的范围内移动Button1了。

  (三)隐藏程序在任务栏的图标

  使用API函数ShowWindow可以隐藏一个程序在任务栏的图标,它被包含在头文件“winuser.h”里面。

  1、隐藏任务栏图标的代码就是:

ShowWindow(Application-$#@62;Handle, SW_HIDE);

  2、要重新显示的时候就使用:

ShowWindow(Application-$#@62;Handle, SW_SHOW);

  但是,如果将程序最小化后,在任务栏的图标就会重新出现。若要在程序还原最小化后,程序在任务栏的图标重新被隐藏起来,可以在窗体的OnPaint事件中加入隐藏程序在任务栏的图标的代码,这样,程序只有在最小化时任务栏才会出现图标,当程序还原最小化时图标又会重新被隐藏起来。


API技巧集(三)




  (四)重启、关闭Windows

  当用户修改了Windows里面的一些设置,Windows经常会提问是否要重新启动计算机,当用户点Yes的时候,计算机将会自动重启。这个就是API函数ExitWindowsEx的一个典型的应用。

  ExitWindowsEx,顾名思义就是退出Windows的函数,它有两个参数,第一个是退出Windows的选项,常用的有:EWX_REBOOT(重新启动计算机),EWX_SHUTDOWN(关闭计算机),EWX_LOGOFF(注销当前用户),第二个参数系统保留没有使用,可设为0。

  在自编的程序中(如:注册表修改程序),当用户修改了某项设置需要重新启动计算机的时候,就要使用EWX_REBOOT选项重启计算机。如:

ExitWindowsEx(EWX_REBOOT,0);

  使用WX_SHUTDOWN选项,可以实现关机。如:

ExitWindowsEx(EWX_SHUTDOWN,0);

  当需要注销的时候,就使用EWX_LOGOFF选项。如:

ExitWindowsEx(EWX_LOGOFF,0);


api技巧集(四)



函数名:

  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标记相同 r>   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);



api技巧集(四)




超级链接效果

  在很多共享软件的关于对话框里有一些模仿网页的超级链接,如主页URL或E-Mail之类的,当鼠标移到它上面的时候,文字变成红色的,当鼠标离开时,文字又变回原来的蓝色,如果用鼠标点击这个链接则会弹出浏览器窗口打开指定的URL或是运行默认的E-Mail程序撰写新邮件,就和真的超链接一样。你是不是也想在你的程序里做一个呢?其实,我们只要调用API函数ShellExecute和在鼠标移动时改变一下文字的颜色,就可以在自己的程序中出现这种效果。

  首先新建一个工程,在窗体Form1上添加两个Label组件,它们的Name属性使用默认的Label1和Label2。

  然后在Form1的OnCreate事件中加入代码:

Label1-$#@62;Cursor=crHandPoint;

Label2-$#@62;Cursor=crHandPoint;

Label1-$#@62;Font-$#@62;Color =clBlue;

Label2-$#@62;Font-$#@62;Color =clBlue;

Label1-$#@62;Caption="主页:初学者之家网站";

Label2-$#@62;Caption="E-Mail:fdlweb@sina.com";

  再在Label1的OnClick(单击)事件中加入:

//蓝色的字请改成自己的主页地址

ShellExecute(Handle,NULL,"http://fdlweb.myrice.com/",NULL,NULL,SW_SHOWNORMAL);

  在OnMouseMove事件中加入:

Label1-$#@62;Font-$#@62;Color=clRed;

  在Label2的OnClick事件中加入:

//蓝色的字请改成自己邮箱地址

ShellExecute(Handle,NULL,"mailto:fdlweb@sina.com",NULL,NULL,SW_SHOWNORMAL);

  在OnMouseMove事件中加入:

Label2-$#@62;Font-$#@62;Color=clRed;

  最后在Form1的OnMouseMove事件中加入:

Label1-$#@62;Font-$#@62;Color=clBlue;

Label2-$#@62;Font-$#@62;Color=clBlue;

  代码输入完了,按F9编译运行程序就看到效果了。



拷贝屏幕

  BitBlt函数可以将一幅位图从一个设备场景拷贝到另一个设备场景,这个函数经常用在抓图程序和游戏编程方面,也可以用来做基于桌面的屏幕保护程序。下面让我们用BitBlt函数来做一个虚假桌面的程序:

  首先,添加一个Image组件到窗体中,将窗体Form1的BorderStyle属性设为:bsNone。

  接着在窗体的OnCreate事件加入程序代码:

Left=0;

Top=0;

Width=Screen-$#@62;Width;

Height=Screen-$#@62;Height;

Image1-$#@62;Left=0;

Image1-$#@62;Top=0;

Image1-$#@62;Width=Screen-$#@62;Width;

Image1-$#@62;Height=Screen-$#@62;Height;

//这句代码就是将桌面拷贝到组件Image1中来存放,

// 其中GetDC(0)返回桌面设备的句柄(HDC)

BitBlt(Image1-$#@62;Canvas-$#@62;Handle,0,0,Screen-$#@62;Width,Screen-$#@62;Height,GetDC(0),0,0,SRCCOPY);

  按F9运行,一个假的桌面就出来了,在这个“桌面”上怎么按鼠标都没有反应,可以用来捉弄人喔!。有些桌面的小游戏也是这么干的,你可以在这个程序的基础上加上更多的功能,如在窗体上加上Label组件和Timer组件,用Timer组件来控制Label组件在窗体上移动,再在窗体Form1的OnKeyDown事件和Image1的OnMouseDown事件中加入关闭窗口的代码“Close();”,最后将编译了的程序的扩展名改为scr,这就成了一个文字在桌面上乱动的屏幕保护程序了。






取得磁盘总空间和剩余空间

  要取得磁盘总空间和剩余空间,最简单直接的方法是调用API函数 GetDiskFreeSpace。

  GetDiskFreeSpace函数有5个参数,第一个参数是要判断可用空间的驱动器名,第二个参数是一个存放每簇扇区数的变量,第三个参数是一个存放每扇区字节数的变量,第四个参数是存放剩余簇数的变量,第五个参数是存放总簇数的变量。套用相应计算磁盘空间的公式即可得出指定驱动器的总空间或剩余空间。

磁盘总空间和剩余空间的计算公式分别为:

  磁盘上剩余空间(字节) = 簇的扇区数 * 扇区的字节数 * 剩余簇数

  磁盘上总空间(字节) = 簇的扇区数 * 扇区的字节数 * 总簇数

下面就是取得C盘的总空间和剩余空间的例子:

unsigned long Sectors,Bytes,Free,Total;

GetDiskFreeSpace("C:\\",&Sectors,&Bytes,&Free,&Total);

//可用空间(单位:MB)

int FreeKB = Bytes * Sectors * Free / 1024;

//总空间(单位:MB)

int TotalKB = Bytes * Sectors * Total / 1024;

ShowMessage("C盘的可用空间有:" + IntToStr(FreeKB) + "MB,总空间有:" + IntToStr(TotalKB) +"MB");



api技巧集(五)

提取图标


  调用API函数ExtractIcon可以提取出在程序文件中的图标,它的头文件是shellapi.h,原型为:

HICON ExtractIcon
(
HINSTANCE hInst, //实例句柄
LPCTSTR lpszExeFileName, //要提取图标的那个程序的文件名
UINT nIconIndex //要提取的图标的索引
);

  调用该函数时,参数hInst一般设为当前应用程序的实例句柄,如:Form1-$#@62;Handle。

  参数lpszExeFileName为需要提取图标的程序文件的完整路径,这个程序文件可以是EXE文件、DLL文件、ICO文件等,只要是包含有图标资源的文件一般都可以提取图标。

  当参数nIconIndex指定一个图标的索引可以返回指向图标的句柄,如指定的文件中不存在图标,则返回零,当参数nIconIndex设为-1,函数返回文件的图标总数。

  函数返回的句柄可以赋给一个用TIcon类声明的变量,再使用该变量的SaveToFile方法就可以把图标保存出来。

例子:

TIcon *Icon = new TIcon();
AnsiString FileName = "C:\\WINDOWS\\SYSTEM\\SHELL32.DLL";
int TotalIcon;
//得到文件SHELL32.DLL的总图标数
TotalIcon = (int)ExtractIcon(Form1->Handle,FileName.c_str(), -1);
//提取第一个图标,0为第一个,1为第二个,类推...
Icon->Handle = ExtractIcon( Form1->Handle, FileName.c_str(), 0);
//保存图标
Icon->SaveToFile("C:\\1.ICO");
  下面给出一个完整的图标提取程序源码。

  这个程序需要四个按钮控件(Button)、四个文本标签控件(Label)、两个文本框控件(Edit)、一个水平滚动条控件(ScrollBar)、一个打开文件对话框控件(OpenDialog)、一个保存文件对话框控件(SaveDialog)和一个图片控件(Image),还有一个Panel控件是装饰用的。界面如图所示:

             

  把各个控件排列好,再把四个Label控件的Caption属性修改一个,最后输入程序代码,运行程序,一个提取图标的程序就出来了,你以后也就不会为没有图标资源可用而发愁了。

程序清单(Unit1.cpp):
//--------------------------------------- ----------------------
#include $#@60;vcl.h$#@62;
#pragma hdrstop
#include "Unit1.h"
//----------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
AnsiString FileName;
TIcon *Icon = new TIcon();
int TotalIcon;
//----------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}

//----------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{

Caption="图标小偷 1.0";
Button1-$#@62;Caption="选择文件";
Button2-$#@62;Caption="保存图标";
Button3-$#@62;Caption="保存所有";
Button4-$#@62;Caption="退出";
Edit1-$#@62;Text=0;
Edit2-$#@62;Text=0;
Image1-$#@62;Width=32;
Image1-$#@62;Height=32;
OpenDialog1-$#@62;Filter="可执行文件(*.exe,*.dll)|*.exe;*.dll|图标文件(*.ico)|*.ico|所有文件(*.*)|*.*";
SaveDialog1-$#@62;Filter="图标文件|*.ico";
ScrollBar1-$#@62;Enabled=false;
Button2-$#@62;Enabled=false;
Button3-$#@62;Enabled=false;

}
//----------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

if(OpenDialog1-$#@62;Execute())
{

TotalIcon = (int)ExtractIcon( Form1-$#@62;Handle, OpenDialog1-$#@62;FileName.c_str(), -1 );
if(TotalIcon$#@62;0)
{

if(TotalIcon$#@60;2)

ScrollBar1-$#@62;Enabled=false;

else

ScrollBar1-$#@62;Max=TotalIcon-1;

Button2-$#@62;Enabled=true;
Button3-$#@62;Enabled=true;
FileName = OpenDialog1-$#@62;FileName;
Edit1-$#@62;Text =TotalIcon;
Icon-$#@62;Handle = ExtractIcon( Form1-$#@62;Handle, FileName.c_str(), 0);
Image1-$#@62;Picture-$#@62;Icon=Icon;
Edit2-$#@62;Text=1;

}
else
{

ShowMessage("该文件没有图标");

}

}

}
//----------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{

if(SaveDialog1-$#@62;Execute())
{

//保存图标
Icon-$#@62;SaveToFile( SaveDialog1-$#@62;FileName);

}

}
//----------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{

if(SaveDialog1-$#@62;Execute())
//提取所有的图标
for(int i=0;i$#@60;TotalIcon-1;i++)
{

Icon-$#@62;Handle = ExtractIcon( Form1-$#@62;Handle, FileName.c_str(), i);
Icon-$#@62;SaveToFile(SaveDialog1-$#@62;FileName+(AnsiString)i+".ico");

}

}
//----------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{

Close();

}
//----------------------------------------------------------------
void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
{

Edit2-$#@62;Text=ScrollBar1-$#@62;Position+1;
Icon-$#@62;Handle = ExtractIcon(Form1-$#@62;Handle, FileName.c_str(),ScrollBar1-$#@62;Position);
Image1-$#@62;Picture-$#@62;Icon=Icon;

}
//----------------------------------------------------------------

判断驱动器的类型


  使用API函数GetDriveType能判断一个驱动器的类型,该函数返回一个int型的值,当返回值为2时,是软盘;为3时,是硬盘;为4时,是网络映射盘;为5时,是光驱;为6时,是 RAM 磁盘;为其它值时,是非法的盘符。这个API函数包含在winbase.h头文件中,首先在程序头部加上语句:

include $#@60;winbase.h$#@62;

包含头文件,然后在程序中加入以下代码就可以判断驱动器的类型:

int drv;
//这里的"C:\\"为要判断的盘符
drv=GetDriveType("C:\\");
switch (drv) //判断drv的值
{
case 2 : //DRIVE_REMOVABLE

ShowMessage("软盘");
break;

case 3 : //DRIVE_FIXED

ShowMessage("硬盘");
break;

case 4 : //DRIVE_REMOTE

ShowMessage("网络映射盘");
break;

case 5 : //DRIVE_CDROM

ShowMessage("光驱");
break;

case 6 : //DRIVE_RAMDISK

ShowMessage("RAM 磁盘");
break;

default :

ShowMessage("这个磁盘不存在!");
break;

}

注:case语句后的数值也可以用注释后的常数替换。如2可用常数 DRIVE_REMOVABLE 来替换。


api技巧集(七)


窗口最小化、最大化和恢复

  通过调用API函数ShowWindow可以控制指定窗口的状态,如将窗口最小化、最大化或者是恢复原来的状态,等等。

  虽然通过窗口标题栏上的控制按钮也可以将窗口最小化、最大化或者是恢复,但ShowWindow函数能实现更多的功能,又如隐藏窗口、将窗口最小化到桌面等,这些是标准的控制按钮所做不到的。

  下面介绍一个ShowWindow函数的例子。这个例子演示了如何将一个窗口最小化到桌面或最小化到任务栏和最大化、恢复窗口原始状态。

  首先,在C++ Builder中新建一个工程,为了方便演示,工程需要两个窗口。添加第二个窗口Form2的方法是:选择“File”菜单下的“New Form”。添加了新窗口后,选择“File”菜单下的“Include Unit Hdr...”包含窗口Form2的头文件“Unit2.h”,或是直接在Form1的代码编辑窗口的头部加上“#include "Unit2.h"”语句。然后在Form1上放上四个按钮,它们的Caption属性分别为“最大化”、“最小化到桌面”、“恢复”和“最小化到任务栏并恢复”。

  接着,双击窗件Form1,在它的OnCreate事件中加入:

void __fastcall TForm1::FormCreate(TObject *Sender)

{

  //设置Form1为顶层窗口

Form1-$#@62;FormStyle=fsStayOnTop;

}

  双击按钮Button1,在它的OnClick事件中加入:

void __fastcall TForm1::Button1Click(TObject *Sender)

{

  //最大化

ShowWindow(Form2-$#@62;Handle, SW_MAXIMIZE);

}

双击按钮Button2,在它的OnClick事件中加入:


void __fastcall TForm1::Button2Click(TObject *Sender)

{ //最小化到桌面

ShowWindow(Form2-$#@62;Handle, SW_MINIMIZE);

}

双击按钮Button3,在它的OnClick事件中加入:

void __fastcall TForm1::Button3Click(TObject *Sender)

{

  //恢复最小化

ShowWindow(Form2-$#@62;Handle, SW_RESTORE);

}

{{??最??苤赵??蛹? 酸???蔑棠奴 ??锸◆ ?硌斯譬 ?拨霾蝌?棠 utton4腔OnClick岈璃?〔????别载陇?ㄛ?洁楼??跺??腔测钨ㄩ

void __fastcall TForm1::Button4Click(TObject *Sender)

{

  //最小化到任务栏

ShowWindow(Application-$#@62;Handle, SW_MINIMIZE);

  //延时1秒

Sleep(1000);

  //恢复最小化

ShowWindow(Application-$#@62;Handle, SW_RESTORE);

}

  最后,编译运行程序。

  获取磁盘序列号、卷标和文件系统类型

  使用API函数GetVolumeInformation,可以获取一个磁盘的有关信息,如磁盘的序列号、卷标、文件系统类型。有些软件就是利用磁盘的序列号来加密的。

  需要获取磁盘信息的时候,加入下面的代码就可以了:

  //定义长度为255的卷标字符串变量缓冲区:

AnsiString VolumeName=AnsiString::StringOfChar(" ", 255);

  //序列号

unsigned long SerialNumber;

  //定义长度为20的文件系统类型字符串缓冲区

AnsiString SystemName = AnsiString::StringOfChar(" ",20);

  //获取磁盘信息

GetVolumeInformation("C:\\", VolumeName.c_str(), 255, &SerialNumber, 0, 0, SystemName.c_str(), 20);

ShowMessage("C盘的卷标:" + Trim(VolumeName));

ShowMessage("C盘的序列号:" + IntToStr(SerialNumber));

ShowMessage("C盘的文件系统类型:" + Trim(SystemName));
  屏幕放大镜

  你一定用过Windows98自带的那个屏幕放大镜吧,你想不想自已做一个呢?其它,这个程序的关键是使用了API函数StretchBlt。

  调用API函数StretchBlt可以把一个设备中指定大小的位图从拷贝到另一个设备,在拷贝的过程中,还可以根据需要来缩放位图。

  下面是它的原型和参数说明:

BOOL StretchBlt

(

HDC hdcDest, //目标设备句柄

int nXOriginDest, //目标矩形左上角的X坐标

int nYOriginDest, //目标矩形左上角的Y坐标

int nWidthDest, //目标矩形的宽度

int nHeightDest, //目标矩形的高度

HDC hdcSrc, //源设备句柄

int nXOriginSrc, //源矩形左上角的X坐标

int nYOriginSrc, //源矩形左上角的Y坐标

int nWidthSrc, //源矩形的宽度

int nHeightSrc, //源矩形的高度

DWORD dwRop //光栅运算操作

);

  StretchBlt函数的头文件为“wingdi.h”。其中,它的dwRop参数有15种操作,最常用的就是拷贝运算SRCCOPY了。当源设备和目标设备指定的矩形大小不相等时,函数会根据源矩形和目标矩形的大小比例对位图进行放大或缩小操作后,拷贝到目标设备中。

  下面就是一个把屏幕上左上角坐标为0x0、宽和高都为100的矩形位图缩小2倍后拷贝到图片控件Image1中的例子:

StretchBlt(Image1-$#@62;Canvas-$#@62;Handle, 0, 0, 50, 50, GetDC(0), 0, 0, 100, 100, SRCCOPY);

  这句代码的GetDC(0)语句为取得桌面设备的句柄。

  如果不断地使用上面那句代码,把屏幕缩小放到Image1中,这就成一个“屏幕缩小镜”了。当然,缩小屏幕并没有什么实际的用处,我们只要把它改一下就可以做成“屏幕放大镜”了。

  要做这个“屏幕放大镜”,首先要运行Borland C Builder,在窗体Form1上放上一个图片控件Image1和一个时间控件Timer1。

双击窗体Form1,在它的OnCreate事件中加入代码:

void __fastcall TForm1::FormCreate(TObject *Sender)

{

Image1-$#@62;Width=200;

Image1-$#@62;Height=200;

Timer1-$#@62;Interval=10;
  //设置顶层窗口

SetWindowPos( Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE||SWP_NOSIZE);

}

  双击时间控件Timer1,在它的OnTimer事件中加入以下代码:

void __fastcall TForm1::Timer1Timer(TObject *Sender)

{

int x,y;

POINT CurPos;

  //取得鼠标当前坐标

GetCursorPos(&CurPos);

  //保证拷贝的图象不在屏幕外

if(CurPos.x $#@62;Screen-$#@62;Width - 100)

x=Screen-$#@62;Width - 100;

else if(CurPos.x $#@60;50)

x=0;

else

x=CurPos.x-50;

if(CurPos.y $#@62;Screen-$#@62;Height-100)

y=Screen-$#@62;Height-100;

else if(CurPos.y $#@60;50)

y=0;

else

y=CurPos.y-50;

Caption="坐标:" + IntToStr(CurPos.x) + "," + IntToStr(CurPos.y);

Image1-$#@62;Canvas-$#@62;FillRect(Rect(0,0,200,200));
  //拷贝放大图象

StretchBlt(Image1-$#@62;Canvas-$#@62;Handle, 0, 0, 200, 200, GetDC(0), x, y, 100, 100, SRCCOPY);

}

  代码输入完了,按F9或点击运行按钮运行程序。怎么样?和Windows自带的那个差不多吧!

  需要注意的是:C++ Builder并象VB那样图片控件可以是非持久性的,在C++ Builder中,并不能直接不断地调用StretchBlt函数来得到连贯的图象,而是要先使用图片控件的FillRect方法填充图片框(相当于清空图片框),再调用StretchBlt函数才行。

  时间的延迟

  延迟在程序设计中非常有意义!比如,程序启动时的等待画面,又或者你需要等待一个过程的完成才能运行程序下面的代码,这时就要使用到时间的延迟了。

  但是在很多编程语言中一般都没有现成的延迟函数。在Dos的C时代,当程序需要延迟时,有不少人使用的是for循环:

for(int i=0;i$#@60;10000;i++);

  到现在也可能还有人在用吧。到了Win32时代,在系统的API函数库里已经提供有时间延迟的函数了,它就是Sleep函数。当然,在Windows编程中,你也可以使用Timer控件,但使用Sleep函数更方便、快捷。我们只需简单的调用一下Sleep函数,就可以实现时间的延迟。

  Sleep函数只有一个参数cMilliseconds,用来指定需要延迟的时间,它的单位是毫秒。让我们看下面的例子,请在一个按钮的单击(OnClick)事件中加入下面的代码:

Sleep(3000);//延迟三秒

ShowMessage("本对话框已经延迟了三秒!");

  这个例子演示了一个延时的对话框,单击了该按钮,本应立即弹出的对话框延迟了三秒钟的时间才弹出。

没有评论: