很多玩游戏的人都知道一般游戏客户端程序是不允许双开的,就是说在同一游戏在启动的时候,是无法打开多个窗口。很多其他软件如酷狗播放器等也是这样。如果把打开的窗口最小化,这时重新启动程序,最小化的窗口会被显示,而不是重新开一个窗口。
    今天突然想把我自己以前做的音乐播放器, 也加这么一个功能。查了点资料,主要用到了FindWindow这个函数。
    原型如下:

HWND FindWindow
(
 LPCSTR lpClassName, //输入窗口的类名,其实需要是注册过的类名才行,否则是要报错或者查找失败的。
 LPCSTR lpWindowName, //输入窗口的名称,就是窗口上面蓝色的那行玩意儿写的字。
);

对于这个函数,如果按照窗口的名称查找,是很简单的,但是会有很多问题。
一开始我就是按窗口的名称来查找,因为不知道类名。

BOOL CMusicPlayerApp::InitInstance()
{
CString strTitle = _T("MusicPlayer");
HWND hwnd = ::FindWindow(NULL, strTitle);
if (hwnd != NULL) {
::SetActiveWindow(hwnd);
ShowWindow(hwnd, SW_NORMAL);
::SetForegroundWindow(hwnd);
return FALSE;
}
}

发现这样有时候是可以运行成功的,有时候是不能运行成功的。为何? 
运行失败的情况是这样的:
      (1)把编译好的程序,放在B文件夹(某个盘上的文件夹)
      (2)打开B文件夹,但不运行里面的程序 。
      (3)在桌面新建文件夹MusicPlayer ,并打开该文件夹。
      (4)运行B文件夹 里的程序,发现程序无法启动,MusicPlayer文件夹变成了当前活动窗口。
出现这样的原因是:程序在用FindWindow来找窗口时,发现桌面上有一个文件夹叫MusicPlayer ,它以为这个就是你要找的程序窗口。于是把MusicPlayer 文件夹作为活动窗口给显示出来了。
可见用窗口名称来查找有点不靠谱,虽然简单,但是不好控制。
     我就想把FindWindow的第一个参数也给它填上,用类名和窗口名同时查找,这样就不会出现上面的情况了。关键类名是什么,开始我猜是播放器界面这个对话框类,发现不是;我把程序用到的类都试了一下,发现也不行。查资料知道:
        MFC并没有一个一个帮我们派生的窗口类进行注册,而是使用的默认窗口类的方式,而默认的窗口类,一般类名都是“#32770(Dialog)”。就是说所有的MFC默认使用都是默认类,而且这个默认类是一样的,这样我在查找窗口的时候,不是很容易和别人写的程序进行撞车吗?
      可不可以自定义自己的类名呢?答案是可以的,但是必须先注册后,才能使用。

比如我要注册的窗口类的对应句柄是IDD_MUSICPLAYER_DIALOG,

那么打开XXX.rc文件后,稍微需找一下就会发现这个数据段:

上面用框子框起来的就是要加的类名,这个名字可以随便起。

然后再APP文件里这上这样的代码:

BOOL CMusicPlayerApp::InitInstance()
{  

  WNDCLASS wc;

  // Get the info for this class.
  // #32770 is the default class name for dialogs boxes.
  ::GetClassInfo(AfxGetInstanceHandle(), "#32770", &wc);

  / Change the name of the class.
  wc.lpszClassName = _T("CMusicPlayerDlg"); //这里请再次注意,一定要保证和rc资源文件里保存的类名相同!

  // Register this class so that MFC can use it.
  AfxRegisterClass(&wc);  HANDLE hObject = CreateMutex(NULL, FALSE, _T("MusicPlayer.exe")  if (ERROR_ALREADY_EXISTS == GetLastError())

  {
    CloseHandle(hObject);
    CString strTitle = _T("MusicPlayer");
    HWND hwnd = ::FindWindow(wc.lpszClassName, strTitle);
    if (hwnd != NULL)
    {

::SetActiveWindow(hwnd);
                  if (IsIconic(hwnd))
                  {
                       ::ShowWindow(hwnd, SW_NORMAL);
                  }
                  else
                  {
                        ::ShowWindow(hwn  d, SW_RESTORE);
                  }
                   SetForegroundWindow(hwnd);

    }
    return FALSE;
  }

.....

}

  

MFC注册窗口类以及FindWindow按窗口类名查询的更多相关文章

  1. MFC注册窗口类以及FindWindow按窗口类名查询(避免用#32770获取窗口句柄)

    呵呵,最近在研究SendMessage函数,其中需要用到m_hWnd,之后延伸着又尝试获得窗口的句柄,于是遇到了FindWindow函数,原型如下: HWND FindWindow ( LPCSTR ...

  2. 窗口类(Window Class)概述

    windows窗口编程(通常意义上的win32)有几个比较核心的概念:入口函数WinMain.窗口类Window Class.窗口过程.消息处理机制.通用控件.本文主要介绍窗口类的相关概念,包括: 窗 ...

  3. 窗口的子类化与超类化——子类化是窗口实例级别的,超类化是在窗口类(WNDCLASS)级别的

    1. 子类化 理论:子类化是这样一种技术,它允许一个应用程序截获发往另一个窗口的消息.一个应用程序通过截获属于另一个窗口的消息,从而实现增加.监视或者修改那个窗口的缺省行为.子类化是用来改变或者扩展一 ...

  4. ATL7窗口类详细剖析

    前言: ATL是微软继MFC之后提供的一套C++模板类库,小巧.精妙.效率极高.它的主要作用是为我们编写COM/DOM/COM+程序提供了丰富的支持.但是ATL只能写COM么?我以前只是MFC程序员的 ...

  5. 探索Win32系统之窗口类(转载)

    Window Classes in Win32 摘要 本文主要介绍win32系统里窗口类的运做和使用机制,探索一些细节问题,使win32窗口类的信息更加明朗化. 在本文中,"类", ...

  6. Window 窗口类

    窗口类 WNDCLASS 总结 总结为下面的几个问题: . 什么是窗口类 . 窗口类的三种类型 . 窗口类各字段含义 . 窗口类的注册和注销 . 如何使用窗口类,子类化.超类化是什么 下面分别描述: ...

  7. 通用窗口类 Inventory Pro 2.1.2 Demo1(下续篇 ),物品消耗扇形显示功能

    本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...

  8. 通用窗口类 Inventory Pro 2.1.2 Demo1(下)

    本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...

  9. 通用窗口类 Inventory Pro 2.1.2 Demo1(中)

    本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...

随机推荐

  1. RabbitMQ 集群+负载均衡

    负载均衡 集群的配置已经搭建好了,代码也成功跑通,成功做到了高可用,但是我们的程序连接节点并不会管哪个服务器在忙.哪个服务器空闲,完全看心情想连谁就连谁.而且代码中要把每个ip的节点都手动的写出来 , ...

  2. BZOJ2588: Spoj 10628. Count on a tree

    传送门 刚开始看错题以为是dfs序瞎搞.. 后来看清题了开始想用树剖瞎搞... 感觉要滚粗啊.. 对于每个点到根的路径建立线段树,暴力建MLE没跑,上主席树,然后$(x,y)$的路径就可以先求出来$L ...

  3. [教程] [授权翻译] 使用补丁修改DSDT/SSDT [DSDT/SSDT综合教程]

    [教程] [授权翻译] 使用补丁修改DSDT/SSDT [DSDT/SSDT综合教程] http://bbs.pcbeta.com/viewthread-1571455-1-1.html [教程] [ ...

  4. pgsql 建数据库注意事项

    在用navacat建好表之后,需要主键自增的时候,把字段建好之后,可以使用下面的sql来建立主键自增. ALTER TABLE "public"."chart_sql&q ...

  5. A*寻路算法探究

    A*寻路算法探究 A*算法常用在游戏的寻路,是一种静态网路中求解最短路径的搜索方法,也是解决很多搜索问题的算法.相对于Dijkstra,BFS这些算法在复杂的搜索更有效率.本文在U3D中进行代码的测试 ...

  6. yii2 开源插件与系统

    yii2干货集:https://github.com/forecho/awesome-yii2 商城 samdark/yii2-shop composer global require "f ...

  7. Vue.js简单实践

    直接上代码,一个简单的新闻列表页面(.cshtml): @section CssSection{ <style> [v-cloak] { display: none; } </sty ...

  8. 子div设置float后导致父div无法自动撑开的问题

    子div设置float后会导致父div无法自动撑开 原因:内部的DIV因为float:left之后,就丢失了clear:both和display:block的样式,所以外部的DIV不会被撑开. 以下是 ...

  9. Android 项目结构图

    src:存放Java源代码 gen:存放系统自动生成的配置文件 Android 4.4.2:包含Android.jar文件,包含构建应用程序所需的所有Android SDK库 asssets:存放资源 ...

  10. 初试PHP单元测试TDD之安装PHPUnit

    东风吹战鼓擂,一年一度的校招季开始了,最为一名即将踏入社会的搬砖工,自然也闲不下来了.各种总结.恶补.面经在所难免.当遇见敏捷开发时,有点蒙了,这是什么东东,绝对不能吃!既然是一种软件开发的方式,听上 ...