windows客户端开发--使你的客户端运行时记住上次关闭的大小和位置

几乎所有的windows客户端都可以调整大小,所以用户根据自己的喜好调整客户端的大小和位置。

但是当该客户端退出后,重新运行客户端的时候,我们往往又要调整自己喜好的大小和位置。

微信的windows客户端做了记住客户端退出时候的大小和位置,下次运行的时候直接,窗口直接显示为你喜好的大小和位置。

现在的任务就是八一八这个小小的功能。

首先,你肯定是想到了使用配置文件。再客户端退出的时候,把客户端窗口的信息记录在一个配置文件中,一般都是.ini文件。读写配置文件 很简单,这里就不再赘述了。

但是使用配置文件的一个致命缺点就是别人很容易发现这个文件,或许可以对其进行一定的修改。

所以,要来一个高大上的方法,让用户不容易找到这个信息。这就是写入到注册区,然后读取注册区,实现记住上次关闭时的windows信息。

你不需要单独存储客户端的width和height等变量,windows为我们提供了一个结构体:

WINDOWPLACEMENT

原型:

typedef struct tagWINDOWPLACEMENT
{ /* wndpl */
UINT length;
UINT flags;
UINT showCmd;
POINT ptMinPosition;
POINT ptMaxPosition;
RECT rcNormalPosition;
} WINDOWPLACEMENT;

意义:

length

length指定了结构的长度,以字节为单位。

flags

flags指定了控制最小化窗口的位置的标志以及复原窗口的方法。这个成员可以是下面列出的标志之一,或都是: · WPF_SETMINPOSITION 表明可以指定最小化窗口的x和y坐标。如果是在ptMinPosition成员中设置坐标,则必须指定这个标志。

showCmd

WPF_RESTORETOMAXIMIZED表明复原后的窗口将会被最大化,而不管它在最小化之前是否是最大化的。这个设置仅在下一次复原窗口时有效。它不改变缺省的复原操作。这个标志仅当showCmd成员中指定了SW_SHOWMINIMIZED时才有效。

showCmd 指定了窗口的当前显示状态。这个成员可以是下列值之一: ·

SW_HIDE 隐藏窗口,使其它窗口变为激活的。

· SW_MINIMIZE 最小化指定的窗口,并激活系统列表中的顶层窗口。

· SW_RESTORE 激活并显示窗口。如果窗口是最小化或最大化的,Windows将把它恢复到原来的大小和位置(与SW_SHOWNORMAL相同)。

· SW_SHOW 激活窗口并按照当前的位置和大小显示窗口。

· SW_SHOWMAXIMIZED 激活窗口并将其显示为最大化的。

· SW_SHOWMINIMIZED 激活窗口并将其显示为图标。

· SW_SHOWMINNOACTIVE 将窗口显示为图标。当前激活的窗口仍保持激活状态。

· SW_SHOWNA 按当前状态显示窗口。当前激活的窗口仍保持激活状态。

· SW_SHOWNOACTIVATE 按最近的位置和大小显示窗口。当前激活的窗口仍保持激活状态。

· SW_SHOWNORMAL 激活并显示窗口。如果窗口是最小化或最大化的,Windows将它恢复到原来的大小和位置(与SW_RESTORE相同)。

ptMinPosition

ptMinPosition 指定了窗口被最小化时左上角的位置。

ptMaxPosition

ptMaxPosition 指定了窗口被最大化时左上角的位置。

rcNormalPosition

rcNormalPosition 指定了窗口处于正常状态(复原)时的坐标。

那么我们如何获得这个struct的信息呢:

GetWindowPlacement函数可以做到:

函数原型

BOOL GetWindowPlacement(HWND hWnd,WINDOWPLACEMENT*lpwndpl);

参数

hWnd:窗口句柄。

lpwndpl:指向WINDOWPLACEMENT结构的指针,该结构存贮显示状态和位置信息。

在调用GetWindowPlacement函数之前,将WINDOWPLACEMENT结构的长度设为

sizeof(WIDNOWPLACEMENT)。如果lpwndpl->length设置不正确则函数GetWindowPlacement将失败。

接下来的任务就是如何写入注册区了,这里我们首先使用MFC中的函数,这样可以更简单一些。

The WriteProfileBinary() is part of the MFC class CWinApp which simply dumps the WINDOWPLACEMENT structure into the registry as a REG_BINARY value called “WP” in a key called MainFrame. A good idea, especially for child windows of the CMainFrame class, is to replace the hard-coded MainFrame with the caption of the frame.

BOOL CMainFrame::DestroyWindow()
{
    WINDOWPLACEMENT wp;
    GetWindowPlacement(&wp);
    AfxGetApp()->WriteProfileBinary("MainFrame", "WP", (LPBYTE)&wp, sizeof(wp));

    return CMDIFrameWnd::DestroyWindow();
}

接下来就是如何从注册区中取数据了:

使用MFC中提供的函数:GetProfileBinary

void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
    CMDIFrameWnd::OnShowWindow(bShow, nStatus);

    static bool bOnce = true;

    if(bShow && !IsWindowVisible()
        && bOnce)
    {
        bOnce = false;

        WINDOWPLACEMENT *lwp;
        UINT nl;

        if(AfxGetApp()->GetProfileBinary("MainFrame", "WP", (LPBYTE*)&lwp, &nl))
        {
            SetWindowPlacement(lwp);
            delete [] lwp;
        }
    }
}

这样就实现了MFC中存取windows的信息了。

接下来会讨论win32 application中如何实现上面的操作。

时间: 2024-10-20 07:30:53

windows客户端开发--使你的客户端运行时记住上次关闭的大小和位置的相关文章

运行时手动伸缩控件大小

public partial class PanelX : UserControl { private Point oldXY; //private static PanelX instance; //public DataRow dr = null; public delegate void RowSelectedEventHandler(object sender, EventArgs e); public event RowSelectedEventHandler RowSelected;

Windows平台开发Mapreduce程序远程调用运行在Hadoop集群—Yarn调度引擎异常

共享原因:虽然用一篇博文写问题感觉有点奢侈,但是搜索百度,相关文章太少了,苦苦探寻日志才找到解决方案. 遇到问题:在windows平台上开发的mapreduce程序,运行迟迟没有结果. Mapreduce程序 public class Test { public static void main(String [] args) throws Exception{ Configuration conf = new Configuration(); conf.set("fs.defaultFS&qu

ACE服务端编程4:ACE跨平台之运行时初始化和关闭

参考APG里的说法:平台差异及不兼容性的一个特别的方面,是对象的运行时初始化和程序关闭时这些对象的相应析构. ACE为了明确管理对象的清理,定义了ACE_Object_Manager类,这个类不仅涉及到对象的管理,还与ACE库的初始化与关闭相关. ACE中应用了大量的设计模式,本篇顺便研究ACE的程序入口函数替换机制分析. ACE库的初始化与关闭 应用要确保在使用ACE库时正确的初始化和关闭,有以下两种常用方式: 1.使用ACE_TMAIN宏作为程序入口函数: 2.使用ACE::init()和A

windows客户端开发--使你的输入框具有拖拽上传的功能

今天谈一天windows客户端拖拽上传功能. 其实主要是拖拽功能,上传是自己实现的. DragAcceptFiles 函数 最重要的就是这个函数了,看看作用: Registers whether a window accepts dropped files 原型: VOID DragAcceptFiles( HWND hWnd, BOOL fAccept ); 参数: hWnd Type: HWND The identifier of the window that is registering

(VB.net)自定义TableLayoutPanel使它能够在运行时用鼠标改变行高和列宽。

喜欢看C#的童鞋,这里有个工具,你们可以自己转换:http://converter.telerik.com/ 想达到这个效果,首先新建一个新的项目.在项目名字上面右击,新增一个类,类名为:TableLayoutPanelEx.vb. 然后只要复制下面的代码到类中即可. Public Class TableLayoutPanelEx Inherits TableLayoutPanel Private Const WM_NCHITTEST As Integer = &H84 Private Cons

运行时设计(Design at Run-time)

1.定义 传统软件开发必须经历“设计时”和“运行时”两个阶段,运行时设计,顾名思义,就是在软件运行过程中,对软件进行实时设计修改,而无需再次进行编译,用户即可使用. “运行时设计(Design at Run-time)”,就是软件在用户使用过程中,可以通过设计器修改界面.功能.甚至对整个页面进行重新定义,保存发布后用户即可使用,而不需经过传统软件漫长的版本发布周期,也与传统快速开发平台功能更新后需要重启服务器,重启客户端等任何重置性操作有本质区别,整个软件修改后,无需编译,发布等过程,而直接保存

Java运行时数据区域

运行时数据区域 Java虚拟机在执行Java程序的过程中会把它管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在, 有些区域则是依赖用户线程的启动和结束而建立和销毁.如图 1.1 程序计数器 是一块内存比较小的空间.作用:用来标志当前线程所执行的字节码的行号指示器(即在字节码中添加编号).在jvm中,字节码解释器工作时就是通过改变这个计数器上的值来选取下一条需要执行的字节码指令.在分支.循环.跳转.异常处理.线程恢复等功能都需要

VS运行时 /MD、/MDd 和 /MT、/MTd之间的区别

程序运行时出现问题,选择的是Release,win64位的模式,并且已经看到了宏定义NDEBUG,但是程序依然进入上面的部分 解决方案是将属性->C/C++->代码生成器->运行库里面的多线程调试(/MTD)修改为多线程DLL(/MD)即可 修改之后: 编译一下 解释原因来自 http://blog.csdn.net/u013829933/article/details/50321355,感谢~~ 这里总结下他们的区别,后面的那个'd'是代表DEBUG版本,没有'd'的就是RELEASE

VC 运行时库 /MD、/MDd 和 /MT、/MTd

这里总结下他们的区别,后面的那个'd'是代表DEBUG版本,没有'd'的就是RELEASE版本了. 首先说/MT /MT是 "multithread, static version ” 意思是多线程静态的版本,定义了它后,编译器把LIBCMT.lib 安置到OBJ文件中,让链接器使用LIBCMT.lib 处理外部符号. /MD是 "multithread- and DLL-specific version” ,意思是多线程DLL版本,定义了它后,编译器把 MSVCRT.lib 安置到O