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

  1. 【MFC】如何在MFC创建的程序中更改主窗口的属性 与 父窗口 WS_CLIPCHILDREN 样式 对子窗口刷新的影响 与 窗体区域绘制问题WS_CLIPCHILDREN与WS_CLIPSIBLINGS

    如何在MFC创建的程序中更改主窗口的属性 摘自:http://blog.sina.com.cn/s/blog_4bebc4830100aq1m.html 在MFC创建的单文档界面中: (基于对话框的, ...

  2. MFC定时关机程序的实现1

    写个定时关机程序自用,界面简单实用,最终界面如下 第一步,新建一个MFC对话框应用程序,拖几个控件过来, 界面如下: 然后给下拉列表框,复选按钮绑定变量,以方便进行操作. CComboBox m_co ...

  3. MFC 只启动一个程序实例

    问题描述: 我们开发过程中可能会经常遇到,只启动一个程序实例.即一个程序启动之后,如果再次执行该程序,将会恢复之前打开的程序,而不是打开一个新的程序. 实现原理:利用FindWindow/FindWi ...

  4. MFC 启动其他程序 变相跳转

    尝试了多种方式之后都无法成功地在对话框程序中弹出一个单文档程序,然后我想到了这个办法. 如果直接在代码中实现某些窗口的弹出比较麻烦,可以采用这个方式来弹出这种窗口. 如果需要传递参数,只需将数据写入文 ...

  5. MFC学习之程序执行过程梳理

    *首先利用全局变量对象theApp启动应用程序.这是由于这个全局对象,基类CWinApp中this的指针才干指向这个对象.假设没有这个全局对象,程序在编译时不会出错,但在执行时就会出错. *调用全局应 ...

  6. MFC中SDI程序创建流程的回顾

    SDI程序创建流程的回顾 从CWinApp.InitialInstance()开始, 1.首先应用程序对象创建文档模板; CSingleDocTemplate* pDocTemplate; pDocT ...

  7. 使用MFC创建C++程序

    编译环境:VS2017 MFC简介: MFC(MicrosoftFoundationClasses)是微软基础类库的简称,是微软公司实现的一个c++类库,主要封装了大部分的windows API函数. ...

  8. MFC多语言程序版本,在不同的windows系统上的使用

    如何使MFC程序界面支持多国语言?这次使用后给自己做一个总结. 我们使用vc6.0的版本来试验 1. 切换到资源视图,右键Dialog->Insert Copy 2. ok后,会出来一个语言的选 ...

  9. MFC vs. SDK程序流程

    大家都知道,windows API编程以及其消息处理,其过程都清晰可见,大体步骤如下: 1)声明消息窗口类 2)注册窗口类 3)createwindows 4)消息获得以及分派(windows pro ...

随机推荐

  1. Oracle数据库备份恢复,巡检须要关注的对象设置以及相关恢复概述

    数据库备份恢复.巡检须要关注的对象设置: 1.数据库名称,以及DBID:  --dbid在v$database中     SYS@ORCL>select dbid,name from v$dat ...

  2. Sqlite 命令行导出、导入数据(直接支持CSV)

    打开命令行 导出数据到data.csv D:\project>sqlite3.exe old.db SQLite version 3.21.0 2017-10-24 18:55:49 Enter ...

  3. STL使用————SET&MULTISET

    SET函数的基本用法 by hhl 使用set的好处 1. 当增加元素后,集合会自动删重并从小到大排列(时间比快排还快)2. 相当于一棵伸展树(能快速求出后继) 使用基础 #include<se ...

  4. thinkphp5项目--企业单车网站(一)

    thinkphp5项目--企业单车网站(一) 项目地址 fry404006308/BicycleEnterpriseWebsite: Bicycle Enterprise Websitehttps:/ ...

  5. 目前常见的三种SQL分页方式:

    --top not in方式 select top 条数 * from tablename where Id not in (select top 条数*页数 Id from tablename) - ...

  6. noip 2018 day1 T3 赛道修建 贪心_树上问题_multiset

    Code: // luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; #define maxn 5000 ...

  7. 海思平台服务器版软件V15.2产品发布

    深度操作系统海思平台服务器版软件是武汉深之度科技有限公司发布的针对华为海思平台的TaiShan系列服务器发布的企业级服务器操作系统软件产品,主要面向企业级服务器应用场景,为用户在国产化平台上提供更具可 ...

  8. Flask--Python中常用的Web框架之一

    Web框架 什么是框架? 协助开发者快速开发web应程序的一套功能代码 开发者只需要按照框架约定要求,在指定位置写上自己的业务逻辑代码即可 为什么要用web框架? 使用web框架的主要目的就是避免重复 ...

  9. [Python] Manipulate Data with Dictionaries in Python

    Dictionaries may be familiar to you as hash maps. In this lesson, you will learn how to create them, ...

  10. Oracle HR 例子用户的建立 10g,11g均可

    Oracle HR 例子用户的建立 10g,11g均可 先将附件(见文章尾部)上的 10 个 .sql 文件放入这个路径中 : $ORACLE_HOME/demo/schema/human_resou ...