MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)

时间:2022-09-12 20:21:37

1.SystemParametersInfo函数可以获取和设置数量众多的windows系统参数

MFC中可以用 SystemParametersInfo(……) 函数来获取和设置系统信息,如下面例子所示,改变的是系统菜单栏的高度。示例:改变系统菜单栏的高度

NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof( NONCLIENTMETRICS );  //这个非常重要,否则下面函数调用将返回0,即ret=0,说明函数调用失败

int ret=::SystemParametersInfo( SPI_GETNONCLIENTMETRICS,sizeof( NONCLIENTMETRICS ),&ncm,0);

//CString str;
//str.Format("return value:%d,%d",ret,ncm.iMenuHeight);
//AfxMessageBox(str);

ncm.iMenuHeight+=10;  //设置系统菜单高度加1
ret=::SystemParametersInfo( SPI_SETNONCLIENTMETRICS,sizeof( NONCLIENTMETRICS ),&ncm,0);

//ret=::SystemParametersInfo( SPI_SETNONCLIENTMETRICS,sizeof( NONCLIENTMETRICS ),&ncm,SPIF_SENDCHANGE);

// 最后一个参数为0或者SPIF_SENDCHANGE,后者表示将把改变写入update win.ini

// str.Format("return value:%d,%d",ret,ncm.iMenuHeight);
// AfxMessageBox(str);

这里要特别说明的是,如果要使用它来设置应用程序的相关属性,请慎重,因为它改变的是操作系统的属性,也就是说系统上其他应用程序的属性也会被改变。

用它来获取系统相关信息,如屏幕宽度、高度、菜单栏、标题栏高度等,还是比较好用的。

函数功能描述:查询或设置系统级参数。该函数也可以在设置参数中更新用户配置文件。

函数原型
B00L SystemParametersinfo(UINT uiAction,UINT uiParam,PVOID pvParam,UINT fWinlni); 参数
uiAction:该参数指定要查询或设置的系统级参数。其取值如下;
SPI_GETACCESSTIMEOUT:
检索与可访问特性相关联的超时段的信息,PvParam参数必须指向某个ACCESSTIMEOUT结构以获得信息,并将该结构中的cbSjze成员和ulParam参数的值设为sizeof(ACCESSTIMEOUT)。 SPI_SETWORKAREA:设置工作区域大小。工作区是指屏幕上没有被系统任务栏或桌面应用程序桌面工具遮盖的部分。参数pvParam是一个指针。指向RECT结构,该结构规定新的矩形工作区域,它是以虚拟屏幕坐标来表达的。在多显示器系统中,该函数用来设置包含特定矩形的显示器工作区域。如果PvParam为NULL,那么该函数将主显示器的工作区域设为全屏。
SPI_GETWORKAREA:检索工作区大小。工作区是指没有被任务遮盖的屏幕部分。
void RunCashDialog::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)  //还是有点点bug,在此页面移动任务栏,然后回到主界面有bug
{
// TODO: Add your message handler code here and/or call default
//lpMMI->ptMaxSize.y = GetSystemMetrics(SM_CYFULLSCREEN) + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME);
CRect rt;
SystemParametersInfo(SPI_GETWORKAREA, , &rt, );
lpMMI->ptMaxSize.x = rt.Width();
lpMMI->ptMaxSize.y = rt.Height();
CDialog::OnGetMinMaxInfo(lpMMI);
}

2.GetWindowRect和GetClientRect

GetWindowRect是取得窗口在屏幕坐标系下的RECT坐标(包括客户区和非客户区),这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置。

   GetClientRect取得窗口客户区(不包括非客户区)在客户区坐标系下的RECT坐标,可以得到窗口的大小,而不能得到相对屏幕的位置,因为这个矩阵是在客户区坐标系下(相对于窗口客户区的左上角)的。  

   ClientToScreen把客户区坐标系下的RECT坐标转换为屏幕坐标系下的RECT坐标.

   ScreenToClient把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标.// 用处?     

我们对同一个窗口先GetWindowRect取得一个RECT,再用ScreenToClient转换到客户坐标系。然后GetClientRect取得一个RECT,再用ClientToScreen转换到屏幕坐标系。显然,GetWindowRect取得的矩阵不小于GetClientRect取得的矩阵。因为前者包含了非客户区,而后包括了客户区。   

  对GetWindowRect取得的矩阵ScreenToClient后,矩阵的大小没有变小,(-3,-29)是窗口的左上角的坐标,相对窗口客户区左上角。   

  对GetClientRect取得的矩阵ClientToScreen后,矩阵也没有变大,新得到的矩阵是窗口客户区在屏幕坐标系上的RECT。

MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)

API:

要取得屏幕大小,可以用下面几个函数:
int  cx   =  GetSystemMetrics( SM_CXFULLSCREEN );
int  cy   =  GetSystemMetrics( SM_CYFULLSCREEN );
通过上边两个函数获取的是 显示屏幕的大小,但不包括任务栏等区域
int  cx   =   GetSystemMetrics(   SM_CXSCREEN   );   
int  cy   =   GetSystemMetrics(   SM_CYSCREEN   );
这两个函数获取的是真正屏幕的大小。

3.WriteProfileString

WriteProfileString是写到系统目录下了,你要用WritePrivateProfileString,这样就可以写到自己定义的任意目录下。

WriteProfileString可以往注册表写也可往INI文件写,关键是SetRegistryKey,如果执行了   SetRegistryKey,那么就会写往注册表,如果没有,就会写往INI文件

有时候,我们需要将初始化信息写入到配置文件中,当程序启动时从这个配置文件中读取这些初始化信息。现在,大部分软件都将这些信息写入到注册表中,然后在启动软件时,从注册表中读取这些初始化信息。但是早期的一些程序都是将这些信息写到Win.ini文件中。该文件位于系统安装根目录下的Windows目录下。
      在程序中,如果想要向Win.ini文件写入一些初始化信息,可以使用WriteProfileString函数来实现。需要注意的是,Windows提供这个函数只是为了兼容16位版本的应用程序,基于Win32的程序应使用注册表来存储初始化信息。WriteProfileString函数原型如下:
  BOOL WriteProfileString(
    LPCTSTR
 lpAppName,   // section name
    LPCTSTR lpKeyName,   // key name
    LPCTSTR lpString        // string to write
  );
      下面,我们建立一个空MFC工程File,在File程序中利用WriteProfileString函数将程序的初始化信息写入Win.ini文件,并将这个操作放置到CFileApp类的InitInstance函数中,在SetRegistryKey函数调用后添加代码。

MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)
 1MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)BOOL CFileApp::InitInstance()
 2MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics){
 3MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)        AfxEnableControlContainer();
 4MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)
 5MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)    // Standard initialization
 6MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)    // If you are not using these features and wish to reduce the size
 7MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)    //  of your final executable, you should remove from the following
 8MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)    //  the specific initialization routines you do not need.
 9MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)
10MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)#ifdef _AFXDLL
11MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)    Enable3dControls();            // Call this when using MFC in a shared DLL
12MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)#else
13MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)    Enable3dControlsStatic();    // Call this when linking to MFC statically
14MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)#endif
15MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)
16MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)    SetRegistryKey(__T("Local AppWizard-Generated Applications"));
17MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)    ::WriteProfileString("http://www.cnblogs.com", "admin", "lantionzy");
18MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)        
19MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)        MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)
20MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)        return TRUE;
21MFC特定函数的应用20160720(SystemParametersInfo,GetWindowRect,WriteProfileString,GetSystemMetrics)}

这段代码将向Win.ini文件写入一些信息,创建一个新的段,名称为:"http://www.cnblogs.com”,在其上创建一个新键,键名为:admin,值为:lantionzy。Build并运行程序,然后打开Win.ini文件,可以看到文件中新添加的段名、键名和其值。
      在CWinApp类中也有WriteProfileString函数,那么它与Win32API中相应函数有什么区别呢?

CWinApp类中WriteProfileString函数声明如下:
      BOOL WriteProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue );
      
可以看到CWinApp类中提供的WriteProfileString函数和Win32API提供的一致。然而使用结果却不一样,在我的机器上,调用CWinApp类的WriteProfileString函数之后,将把信息写到注册表中,而不是Win.ini文件中。
      将上述代码中的第17行改成这样:(去掉域名解析符::)

      WriteProfileString("http://www.cnblogs.com", "admin", "lantionzy");

运行File程序,然后打开注册表,将会看到我们刚刚写入的信息位于:HKEY_CURRENT_USER/Software/Local AppWizard-Generated Applications/File子项下,而且该注册表项与File程序中写进的信息相同。

备注:在不同操作系统环境下,CWinApp类中提供的WriteProfileString函数会把信息存储到不同的地方,或者写到Win.ini文件中,或者写入注册表中。例如:在Windows NT系统下,该函数把信息存储到注册表中;在Windows 3.X系统下,信息被写入Win.ini文件中。

4.GetSystemMetrics

int WINAPI GetSystemMetrics( __in intnIndex);

下面是GetSystemMetrics函数参数nIndex的定义:

SM_ARRANGE 标志用于说明系统如何安排最小化窗口..详细请参看下方备注.:

根据显示器显示的不同,系统数据可能有所不同.

该SM_ARRANGE设置指定系统如何安排最小化窗口,并包含一个起始位置和方向。起始位置可为下列值之一。

Value

Meaning

ARW_BOTTOMLEFT

开始在左下角的屏幕(默认位置) 。

ARW_BOTTOMRIGHT

开始在右下角的屏幕上。相当于ARW_STARTRIGHT.

ARW_HIDE

在屏幕可见区域,隐藏并最小化窗口。.

ARW_TOPLEFT

从左上角的屏幕上。相当于ARV_STARTTOP.

ARW_TOPRIGHT

相当于ARW_STARTTOP | SRW_STARTRIGHT 。

方向的安排可以为下列值之一。

Value

Meaning

ARW_DOWN

纵向排列,从上到下。

ARW_LEFT

水平排列,从左到右。

ARW_RIGHT

水平排列,从右到左。

ARW_UP

纵向排列,从下到上。

5.MoveWindow and SetWindowPos

MoveWindow只能设置窗口的大小和位置;

SetWindowPos拥有MoveWindow的全部功能之外,还可以设置窗口的层叠关系(如,把指定的窗口放在所有窗口的最上层--always   on   top就可以用这个函数、或者把指定的窗口放在另一个窗口的下层,等等)。

没有什么优缺点可言,只是功能上的大小有别。你完全可以不用MoveWindow,而只用SetWindowPos;但是,在只要设置窗口大小或位置的情况下,你也完全可以使用MoveWindow.

void   MoveWindow(   int   x,   int   y,   int   nWidth,   int   nHeight,   BOOL  bRepaint   =   TRUE   );  
void   MoveWindow(   LPCRECT   lpRect,   BOOL   bRepaint   =   TRUE   );

参数  
x指定了CWnd的左边的新位置。  
y指定了CWnd的顶部的新位置。  
nWidth指定了CWnd的新宽度。  
nHeight指定了CWnd的新高度。

bRepaint指定了是否要重画CWnd。如果为TRUE,则CWnd象通常那样在OnPaint消息处理函数中接收到一条WM_PAINT消息。如果这个参数为FALSE,则不会发生任何类型的重画操作。这应用于客户区、非客户区(包括标题条和滚动条)和由于CWnd移动而露出的父窗口的任何部分。当这个参数为FALSE的时候,应用程序必须明确地使CWnd和父窗口中必须重画的部分无效或重画。lpRectCRect对象或RECT结构,指定了新的大小和位置。说明这个函数改变窗口的位置和大小。对于顶层的CWnd对象,x和y参数是相对于屏幕的左上角的。对于子对象,它们是相对于父窗口客户区的左上角的。  
    MoveWindow函数发送一条WM_GETMINMAXINFO消息。处理这个消息时,CWnd得到一个改变最大和最小的窗口缺省值的机会。如果传递给MoveWindow成员函数的参数超过了这些值,则在WM_GETMINMAXINFO处理函数中可以用最小或最大值来代替这些值。   
    
    
    BOOL   SetWindowPos(   const   CWnd*   pWndInsertAfter,   int   x,   int   y,  int   cx,   int   cy,UINT   nFlags   );  
返回值如果函数成功,则返回非零值;否则返回0。  
    参数pWndInsertAfter标识了在Z轴次序上位于这个CWnd对象之前的CWnd对象。这个参数可以是指向CWnd对象的指针,也可以是指向下列值的指针:l   wndBottom       将窗口放在Z轴次序的底部。如果这个CWnd是一个顶层窗口,则窗口将失去它的顶层状态;系统将这个窗口放在其它所有窗口的底部。l   wndTop       将窗口放在Z轴次序的顶部。

l   wndTopMost       将窗口放在所有非顶层窗口的上面。这个窗口将保持它的顶层位置,即使它失去了活动状态。wndNoTopMost       将窗口重新定位到所有非顶层窗口的顶部(这意味着在所有的顶层窗口之下)。这个标志对那些已经是非顶层窗口的窗口没有作用。有关这个函数以及这些参数的使用规则参见说明部分。x指定了窗口左边的新位置。y指定了窗口顶部的新位置。cx指定了窗口的新宽度。cy指定了窗口的新高度。nFlags指定了大小和位置选项。这个参数可以是下列值的组合:l   SWP_DRAWFRAME       围绕窗口画出边框(在创建窗口的时候定义)。

l   SWP_FRAMECHANGED       向窗口发送一条WM_NCCALCSIZE消息,即使窗口的大小不会改变。如果没有指定这个标志,则仅当窗口的大小发生变化时才发送WM_NCCALCSIZE消息。

l   SWP_HIDEWINDOW       隐藏窗口。SWP_NOACTIVATE       不激活窗口。如果没有设置这个标志,则窗口将被激活并移动到顶层或非顶层窗口组(依赖于pWndInsertAfter参数的设置)的顶部。

l   SWP_NOCOPYBITS       废弃这个客户区的内容。如果没有指定这个参数,则客户区的有效内容将被保存,并在窗口的大小或位置改变以后被拷贝回客户区。l   SWP_NOMOVE       保持当前的位置(忽略x和y参数)。

l   SWP_NOOWNERZORDER       不改变拥有者窗口在Z轴次序上的位置。

l  SWP_NOREDRAW       不重画变化。如果设置了这个标志,则不发生任何种类的变化。这适用于客户区、非客户区(包括标题和滚动条)以及被移动窗口覆盖的父窗口的任何部分。当这个标志被设置的时候,应用程序必须明确地无效或重画要重画的窗口和父窗口的任何部分。

l   SWP_NOREPOSITION       与SWP_NOOWNERZORDER相同。

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

l   SWP_NOSIZE       保持当前的大小(忽略cx和cy参数)。

l   SWP_NOZORDER       保持当前的次序(忽略pWndInsertAfter)。

l   SWP_SHOWWINDOW       显示窗口。