VC API常用函数简单例子大全十二(上)

第一百一十一个SizeofResource获取一个资源的大小

函数定义:DWORD SizeofResource(

HMODULE hModule,//模块句柄,同FindResource,LoadResource的模块句柄一样

HRSRC hResInfo//资源位置句柄,是FindResource函数返回的句柄

);

例子:自定义资源,EXE文件包含DLL,双击该EXE文件释放里面的DLL文件到当前目录

首先我们新建一个控件台工程,你也可以新建一个WIN32工程,由于这里建的不是MFC工程,所以还得往工程里添加资源文件,步骤是文件->新建,在弹出的对话框中选择“文件”选项标签,然后选中“资源脚本”,我们要建的就是这个文件,取名、确定、完成。

接着我们进入资源视图(ResourceView),右击资源文件,选择引入(记得把文件类型选所有),选择一个DLL文件,点引入。这时候会弹出一个对话框,提示你给自定义资源类型取类型名,记住这个类型名对应着FindResource函数的第三个参数lpType,取名为DLL,确定,接着我们只要查看一下这个自定义资源的ID号,就可以去敲代码了。方法是右击资源文件,选择"资源符号",这里我查看的对应ID号是101。好了进入代码编辑区,键入如下代码:

#include
int main()
{
 HRSRC hRsrc=FindResource(NULL,MAKEINTRESOURCE(101),"DLL");//查找资源位置
 DWORD dllSize=SizeofResource(NULL,hRsrc);//获取资源大小
 HGLOBAL hGlobal=LoadResource(NULL,hRsrc);//加载资源到内存
 LPVOID pBuffer=LockResource(hGlobal);//获取内存首地址
 char pathName[100];
 GetModuleFileName(NULL,pathName,100);//获得应用程序完整路径名
 int i=0;
 while(pathName[i]!='\0') i++;//计算路径名字符串最后的位置
 //把exe改成dll,然后创建文件
 pathName[i-1]='l';
 pathName[i-2]='l';
 pathName[i-3]='d';
 HANDLE hFile=CreateFile(pathName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,NULL);//创建文件
 DWORD dwSize;
 WriteFile(hFile,pBuffer,dllSize,&dwSize,NULL);//写入数据
 return 0;
}

运行,然后把生成的EXE程序随便复制到一个目录下,双击运行一下。看不是在同一目录下释放出了一个DLL文件。

这可以应用到任何文件上,像可以让一个EXE文件里包含两个EXE文件,当执行这个EXE文件后,会释放出两个EXE文件,然后删除自身。

第一百一十二个SetLayeredWindowAttributes设置窗口透明度

函数定义:BOOL SetLayeredWindowAttributes(         
    HWND hwnd,//要设置的窗口句柄
    COLORREF crKey,//如果窗口一个像素颜色值等于crKey,那么这个像素将是透明的
    BYTE bAlpha,//取值范围0到255,0表示全透明,255表示不透明
    DWORD dwFlags//指定crKey还是bAlpha值有效,LWA_COLORKEY(0x1)指定crKey值有效,bAlpha值无效,

//LWA_ALPHA(0x2)表  示  bAlpah值有效,crKey值无效。LWA_COLORKEY|LWA_ALPHA表示两者都有效
);

想要调用SetLayeredWindowAttributes设置窗口透明度,必须让窗口具有WS_EX_LAYERED(0x80000)扩展样式,可用SetWindowLong函数设置,该函数用法参考API 常用函数第九十八个。而SetLayeredWindowAttributes函数在动态链接库user32.dll里面,关于调用动态链接库里的函数请参考之前的例子,本例采用第二种方法用LoadLibrary,这个函数的用法不懂的可以参考 API常用函数第四十九个。

这里的窗口依旧以无标题记事本为例

#include
int main()
{
 HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
  SetWindowLong(wnd,GWL_EXSTYLE,GetWindowLong(wnd,GWL_EXSTYLE)|0x80000);
 typedef BOOL (WINAPI *FSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
 FSetLayeredWindowAttributes SetLayeredWindowAttributes ;
 HINSTANCE hInst = LoadLibrary("User32.DLL");
 SetLayeredWindowAttributes = (FSetLayeredWindowAttributes)GetProcAddress(hInst,"SetLayeredWindowAttributes");
  int value=0;
 while(1)
  {
  if(value==256) value=0;
  SetLayeredWindowAttributes(wnd,RGB(0,0,0),value,0x2);//0x2 让第二个参数无效。
   value++;
   Sleep(50);
 }
 return 0;
}
第一百一十三个SetROP2设置DC画图模式

通常情况下,如果不调用SetROP2函数设置画图模式,那么默认的DC画图模式就是R2_COPYPEN(直接用源值覆盖),以Rectangle函数来举例,选入一个红色画刷,如:

HBRUSH brush=CreateSolidBrush(RGB(255,0,0));

SelectObject(hdc,brush);那么调用Rectangle在一个窗口里画一个0,0,100,100的矩形就是

Rectangle(hdc,0,0,100,100);

如果没调用Rectangle之前,窗口这部分区域全是绿色,

如下图:

VC API常用函数简单例子大全十二(上)_第1张图片


(为了方便,把这个称为dest)

那么调用Rectangle之后,这部分区域应该是这样的:

VC API常用函数简单例子大全十二(上)_第2张图片


(这个就称为src)

这两个区域每一个像素都有一个RGB颜色值,如0,255,0和255,0,0,而Rectangle所要做的就是合并这样两个区域(dest和src),由于采用R2_COPYPEN画图模式,直接用src覆盖掉dest,那么最终在窗口里显示的结果应该全是红色,也就是每个像素值都是红色。

又如R2_MASKPEN模式,这个是采用按位与(AND)合并两幅图片。两张图片的对应像素颜色值进行按位与运算。

也就是RGB(0,255,0)&RGB(255,0,0)的结果就是窗口最终显示的像素颜色。

那么如果用SetROP2设置画图模式为R2_MASKPEN,再调用Rectangle,窗口显示的应该是这样:

红蓝按位与合并后的结果。RGB(0,255,0)&RGB(255,0,0)的结果是0,也就是颜色值RGB(0,0,0)黑色。

类似的,还有按位或,按位异或,取反等运算,现给出所有模式及运算解释(来自Programming Windows with MFC)

R2_NOPdest = destR2_NOTdest = NOT destR2_BLACK dest = BLACKR2_WHITEdest = WHITER2_COPYPEN dest = srcR2_NOTCOPYPEN dest = NOT srcR2_MERGEPENNOT dest = (NOT dest) OR srcR2_MASKPENNOT dest = (NOT dest) AND srcR2_MERGENOTPENdest = (NOT src) OR destR2_MASKNOTPEN dest = (NOT src) AND destR2_MERGEPEN dest = dest OR srcR2_NOTMERGEPEN dest = NOT (dest OR src)R2_MASKPEN dest = dest AND srcR2_NOTMASKPENdest = NOT (dest AND src)R2_XORPENdest = src XOR destR2_NOTXORPENdest = NOT (src XOR dest)

 例子:以R2_MASKPEN 画图模式在窗口里画一个矩形

#include
int main()
{

 HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
 HDC dc=GetWindowDC(wnd);
 HBRUSH brush=CreateSolidBrush(RGB(100,255,255));
 SelectObject(dc,brush);
 SetROP2(dc,R2_MASKPEN);
 while(1)
 {
  Rectangle(dc,0,0,200,200);
  Sleep(200);
 }
 return 0;
}

运行效果:

VC API常用函数简单例子大全十二(上)_第3张图片


用另外几种模式试一下,看看结果又会有什么不同。

第一百一十四个SetMapMode设置DC映射模式
默认的模式是MM_TEXT,一个单位等于一个像素,也就是当你调用Rectangle等函数画图时,参数的单位是像素,如Rectangle(hdc,0,0,100,100);此时的0,0是窗口的左上角,一个宽300,高300像素的矩形.
而如果把模式换一下的话,结果就不是这样了,像MM_LOMETRIC模式的单位就是0.1毫米,那么Rectangle(hdc,0,0,100,100)所画的矩形应该是100*0.1mm宽,100*0.1mm高,也就是1厘米宽高,但真设置NM_LOMETRIC模式,再调用Rectangle(hdc,0,0,100,100)后,并不会在窗口里显示一个矩形,这是为什么呢,窗口所对应的坐标不同.
 NM_TEXT模式下窗口左上角对应坐标点0,0,往右往下都是递增,如下图:

VC API常用函数简单例子大全十二(上)_第4张图片

而除了自定义模式,和NM_TEXT模式,窗口的坐标都是这样的:

VC API常用函数简单例子大全十二(上)_第5张图片

那么如果窗口坐标处在这种模式下,想在窗口里画矩形,Y坐标必须为是负数,所以上面的Rectangle调用应该是这样Rectangle(0,0,100,-100);而这里的单位是0.1mm

下面给出各种模式及解释

MM_TEXT 1 pixel  

MM_LOMETRIC 0.1 mm  

MM_HIMETRIC  0.01 mm  

MM_LOENGLISH  0.01 in.  

MM_HIENGLISH 0.001 in.  

MM_TWIPS  1/1440 in. (0.0007 in.)  

MM_ISOTROPIC User-defined (x and y scale identically)  User-defined

MM_ANISOTROPIC User-defined (x and y scale independently) User-defined

in.是英寸的缩写.

例子在一个窗口画一根5厘米长的直线,映射模式为MM_LOMETRIC

#include
int main()
{

 HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
 HDC dc=GetDC(wnd);
 ::SetMapMode(dc,MM_LOMETRIC);//设置映射模式
 while(1)
 {
 MoveToEx(dc,0,-50,NULL);
 LineTo(dc,500,-50);//500不是像素,单位是0.1mm
  Sleep(200);
 }
 return 0;
}
//用尺子去量一下那根线,看是不是五厘米,没尺子?没关系,用PS建一个
//五厘米的宽的图像,对比一下。

第一百一十五个DPtoLP将设备坐标转换成逻辑坐标

其实就是将MM_TEXT模式(以像素为单位)坐标点转换成当前模式下的坐标,比如在MM_TEXT模式下150,150这个坐标点位置在MM_LOMETRIC模式里是在哪里。也就是说50*0.1mm是多少像素。

先来看下面这个例子,将150,150这个在MM_TEXT模式下的坐标点转换成MM_LOMETRIC模式下对应的坐标点.

#include
#include
int main()
{

 HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
 HDC dc=GetDC(wnd);
 POINT pt;
 pt.x=pt.y=150;

//设置当前模式,针对当前模式而转换,如果不设置,默认是MM_TEXT,MM_TEXT转MM_TEXT结果还是一样
 SetMapMode(dc,MM_LOMETRIC);

 DPtoLP(dc,&pt,1);//dc是设备上下文,第二个参数是一个POINT指针,第三个指明数组数量。用于多个转换

                           //如:POINT pt[2]={{100,100},{200,200}};DPtoLP(dc,pt,2);
 cout<  return 0;
}
我这儿的输出结果是 469,-469

具体依据电脑设置而定,也就是说在MM_LOMETRIC模式下469,-469这个坐标点和MM_TEXT模式下100,100这个坐标点的位置是相同的。

例子:在一个窗口里的两种模式下画同一长度的线

#include
int main()
{

 HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
 HDC dc=GetDC(wnd);
 POINT ptText[2]={{0,50},{200,50}};//MM_TEXT模式下直线两点
 POINT ptLOME[2]={{0,100},{200,100}};//MM_LOMETRIC模式下直线两点
 SetMapMode(dc,MM_LOMETRIC);//设置模式
 DPtoLP(dc,ptLOME,2);//转换成MM_LOMETRIC对应的坐标点
 while(1)
 {
 MoveToEx(dc,ptLOME[0].x,ptLOME[1].y,NULL);
 LineTo(dc,ptLOME[1].x,ptLOME[1].y);
 SetMapMode(dc,MM_TEXT);//模式改回来
 MoveToEx(dc,ptText[0].x,ptText[1].y,NULL);
 LineTo(dc,ptText[1].x,ptText[1].y);
 Sleep(300);
 SetMapMode(dc,MM_LOMETRIC);//设置模式
 }
 return 0;
}

既然可以转过去,也当然可以转回来

 DPtoLP用于把像素单位转换成其它模式单位,它的参数是以像素为单位的,转换后值的单位就是当前模式对应的单位,面LPtoDP正好相反,它参数的单位是以当前模式为准的,用于把其它模式下的坐标点转换成MM_TEXT模式下的。如模式MM_LOMETRIC,把上面的469,-469转换成对应像素单位就是POINT pt={469,-469};LPtoDP(dc,&pt,1);//记得要设置模式。

你可能感兴趣的:(#,VC,API常用函数简单例子大全,c++)