1. 程式人生 > >Win32程式多顯示器情況下顯示視窗

Win32程式多顯示器情況下顯示視窗

近來在做多顯示器下顯示視窗到特定顯示器上,並且有F11切換全屏和非全屏的功能。現總結如下:

1、先來看如何解決多顯示器顯示特定視窗的問題。

我們分如下幾步走:

第一步,建立一個win32視窗。建立一個視窗是有套路可循的,我將程式碼貼出來,並加以註釋了。

第二步,找出所有的顯示器,然後將視窗顯示在特定的顯示器上。

	HINSTANCE _hInst;					// 當前例項
	TCHAR* szTitle;					// 標題欄文字
	TCHAR* szWindowClass;			// 主視窗類名

	//生成的視窗控制代碼
	HWND _hWnd;

	UINT width;

	UINT height;

	int startx;

	int starty;

	vector<ALLMONITORINFO> mInfo;

	BOOL Create(WNDPROC proc)
	{
		//如果已經建立了一個視窗那麼不再重複建立
		if (_hWnd != NULL)
			return FALSE;

		//返回模組的控制代碼
		_hInst = GetModuleHandle(NULL);

		/*--------------註冊一個視窗類------------------------*/
		WNDCLASSEX wcex;
		memset(&wcex, 0, sizeof(wcex));

		wcex.cbSize = sizeof(WNDCLASSEX);
		wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;

		//設定其回撥函式
		if (proc != NULL)
			wcex.lpfnWndProc = proc;
		else
			wcex.lpfnWndProc = this->MyWndProc;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = _hInst;

		wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
		wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
		//wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_WIN01);//不要選單欄
		wcex.lpszClassName = szWindowClass;//主視窗類名
		//註冊視窗類,這個是必須的,要不然下面的CreateWindow函式總返回NULL
		ATOM atom = RegisterClassEx(&wcex);
		/*-----------------------------------------------*/


		/*--------------獲取所有顯示器資訊------------------------*/
		mInfo.clear();
		//get number of monitors
		mInfo.reserve(GetSystemMetrics(SM_CMONITORS));
		//這個函式很重要,然後回撥函式MonitorEnumProc是獲取所有顯示器資訊的重要函式。
		EnumDisplayMonitors(NULL, NULL, this->MonitorEnumProc, reinterpret_cast<LPARAM>(&mInfo));

		//如果只有一個顯示器的話,那就在這唯一的顯示器上顯示視窗
		if (mInfo.size() == 1)
		{
			RECT rect = mInfo[0].rect;
			width = rect.right - rect.left;
			height = rect.bottom - rect.top;
			startx = rect.left;
			starty = rect.top;
		}
		for (int i = 0; i < mInfo.size(); i++)
		{
			//如果有多個顯示器的話,就在第一個非主屏的顯示器上顯示。
			if (!mInfo[i].isPrimary)
			{
				RECT rect = mInfo[0].rect;
				width = rect.right - rect.left;
				height = rect.bottom - rect.top;
				startx = rect.left;
				starty = rect.top;
				break;
			}
		}
		/*-----------------------------------------------*/


		_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
			startx,starty, width, height, NULL, NULL, _hInst, NULL);

		if (!_hWnd)
		{
			return FALSE;
		}
		//ToggleFullScreen();

		ShowWindow(_hWnd,  SW_SHOW);
		UpdateWindow(_hWnd);
	
		return TRUE;
	}

關於ALLMONITORINFO結構體定義,如下:

struct ALLMONITORINFO
{
	HMONITOR hMonitor;
	RECT     rect;
	bool     isPrimary;
};
回撥函式MonitorEnumProc的定義如下:
BOOL CALLBACK MonitorEnumProc(__in  HMONITOR hMonitor, __in  HDC hdcMonitor, __in  LPRECT lprcMonitor, __in  LPARAM dwData)
	{
		vector<ALLMONITORINFO>& infoArray = *reinterpret_cast<vector<ALLMONITORINFO>* >(dwData);

		ALLMONITORINFO monitorInfo;
		monitorInfo.hMonitor = hMonitor;
		monitorInfo.rect = *lprcMonitor;

		HMONITOR priMonitor = MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY);
		if (priMonitor == hMonitor)
			monitorInfo.isPrimary = true;
		else
			monitorInfo.isPrimary = false;
		
		infoArray.push_back(monitorInfo);
		return TRUE;
	}

2、然後是全屏和非全屏切換的問題。

在網上搜索的時候,給出的答案很多是說用ChangeDisplaySettings這個函式。但是經測試,這個函式不起作用。好象是微軟已經摒棄了這個方法了,在新的系統上已經不起作用了,取而代之的是SetWindowLong這個函式。

程式碼如下所示:

	void ToggleFullScreen(int width, int height, int startx, int starty)
	{
		if(isFullScreen)
		{

			SetWindowLong(_hWnd, GWL_STYLE, GetWindowLong(_hWnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW);

			//GWL_EXSTYLE  extended style擴充套件格式。WS_EX_WINDOWEDGE  使得視窗顯示,並不覆蓋下面的工作列。
			SetWindowLong(_hWnd, GWL_EXSTYLE, GetWindowLong(_hWnd, GWL_EXSTYLE) | WS_EX_WINDOWEDGE);

			//SetWindowPos(_hWnd, NULL, startx, starty, width, height, SWP_SHOWWINDOW);// SWP_FRAMECHANGED);
		}
		else
		{
			LONG curWinStyle = GetWindowLong(_hWnd, GWL_STYLE);
			curWinStyle = curWinStyle & ~WS_OVERLAPPEDWINDOW;
			SetWindowLong(_hWnd, GWL_STYLE, curWinStyle | WS_POPUP);
			MoveWindow(_hWnd, startx, starty, width, height, TRUE);
		}
		isFullScreen = !isFullScreen;
	}


相關推薦

Win32程式顯示器情況顯示視窗

近來在做多顯示器下顯示視窗到特定顯示器上,並且有F11切換全屏和非全屏的功能。現總結如下: 1、先來看如何解決多顯示器顯示特定視窗的問題。 我們分如下幾步走: 第一步,建立一個win32視窗。建立一個視窗是有套路可循的,我將程式碼貼出來,並加以註釋了。 第二步,找出所有的

elementUI el-select 情況包含全部選項,及獲得選中項的label

<template> <div> <span style="margin-left:30px;font-weight:bolder;">教練: <el-select v-model="staffId" pla

VC 各種情況視窗控制代碼的獲取

AfxGetMainWnd AfxGetMainWnd獲取自身視窗控制代碼 HWND hWnd = AfxGetMainWnd()->m_hWnd; GetTopWindow 函式功能:該函式檢查與特定父視窗相聯的子視窗z序(Z序:垂直螢幕的方向,即疊放

Spring Bean作用域為情況的注入問題

測試程式碼: @RestController @Scope("prototype") public class TestController { private static TestSer

Python版本情況四種快速進入交互式命令行的操作技巧

ext 進入 nbsp 情況 交互 菜單 只需要 創建 如何 因為工作需求或者學習需要等原因,部分小夥伴的電腦中同時安裝了Python2和Python3,相信在Python多版本的切換中常常會遇到Python傻傻分不清楚的情況,今天小編整理了四個操作技巧,以幫助大家解決這個

GridView在不寫後端程式碼繫結資料來源且無資料的情況顯示腳註行Footer的新方法

        記錄一下今天解決的一個需求,GridView在頁面上用SqlDataSource控制元件配置資料來源直接繫結,不用後臺程式碼動態繫結,然後為了方便插入資料,在參考了各位大佬的博文後,採用了在欄位的腳註行裡插入文字框控制元件,收集各列的資料,然後在後臺用S

前端頁面情況函式的命名與函式方法的呼叫

與上一篇有些類似之處,都是在處理前端頁面不斷增多,頁面間不斷的拼接與巢狀,頁面與頁面間的函式方法的命名和dom元素一樣出現了命名頭疼的問題,比如說在easyUI前端框架下就是如此,我的解決辦法還是採用資料結構的方法,不同面板,不同頁面間的函式均放在資料結構下進行維護和管理,

前端頁面情況id的命名與初始化

id的命名,貌似就是給dom節點隨便起個名字的事,只要不重複了就行,這個看似簡單,實際上有時候卻比較的麻煩。 在編寫前端頁面時,隨著頁面的不斷增多,頁面間不斷巢狀,不斷拼接的前提下,由於dom元素的不斷增多,各頁面dom元素的id命名和dom元素的初始化就變得更加的棘手了

顯示器環境中移動視窗到指定的顯示器

  //顯示器資訊結構體 typedef struct _tagMyMonitorInfo_t { HMONITOR hMonitor; MONITORINFOEX info; _tagMyMonitorInfo_t() { ZeroMemory(this,

程式 - 未授權情況獲取使用者頭像、暱稱

詳情參考官方文件 開放能力 open-data .wxml檔案中,獲取頭像、暱稱程式碼如下: <open-data type="userAvatarUrl"></open-data> <open-data type="userNickName"></

easyui 判斷select拉框是否選,情況清空預設值

$("#checkType").combobox({ onSelect: function(param){ if (param

Python版本情況快速進入互動式命令列非常實用的四個小技巧!

上一篇文章中,小編已經教過大家安裝Python環境了。這篇文章我來教大家如何辨別多版本Python的切換問題,我主要整理了一下四個技巧,希望能幫大家拔出這根眼中刺!   1、直接在命令列視窗中輸入命令“python”,便可以進入命令行了,如下圖所示。  

MFC中CEdit情況,呼叫GetLine()時,發現老是後面跟有亂碼【轉載】

MFC中CEdit多行情況下,呼叫GetLine()時,發現老是後面跟有亂碼。即使你把str初始化也是如此。 對於採用GetLine()呼叫,其函式說明有2種。 1.int GetLine( int nIndex, LPTSTR lpszBuffer ) co

樹莓派上手--無顯示器情況配置串列埠config.txt

1.       首先確認波特率設定正確,為115200 2.      向microSD卡中燒錄樹莓派官方的映象後,先不要急著把它插入樹莓派中。 3.      在電腦上開啟microSD卡,按如下方式修改config.txt和cmdline.txt這兩個檔案, 4.  

程序情況檔案控制代碼共享的問題

1 Linux中的父子程序 fork() 和 clone()系統呼叫可用來建立新的程序。這兩個系統呼叫結束時,核心在系統的實體記憶體中為新的程序分配新的 task_struct 結構,同時為新程序要使用的堆疊分配物理頁。Linux 還會為新的程序分配新的程序識

Qt 實現在隱藏標題欄情況視窗的縮放(未成功)

呃,這是一個悲劇的版本,在這版本中,我按照網上大神的說法,試了一下,但是沒有效果,不知道出錯在了那裡,和昨天一樣,也是,沒有理想的效果,這裡貼上程式碼,記錄一下 資料連線:放評論 需要包含標頭檔案

C++實用小程式,如何隱藏和顯示視窗

這段神奇的程式碼做到了這個。 ShowWindow(hWnd,0);//隱藏 ShowWindow(hWnd,1);//顯示 #include<windows.h> void WinChange(){ HWND hWnd=GetFor

Retrofit(OKHttp)BaseUrl情況url實時自動替換完美解決方法

前言 多數專案中會出現用到多個BaseUrl的情況,而Retrofit未提供實時切換BaseUrl的方法,且我們在使用Retrofit以及OkHttp時,通常使用單例模式建立Retrofit和OkHttpClient,也不可能每個請求都建立一個Retrofit例項。

spring rmi ip情況出現的問題

在java Main中增加引數,即改為,java -Djava.rmi.server.hostname=192.168.1.101 Main 在初始化時增加如下程式碼,System.setProperty(“java.rmi.server.hostname” , “192.168.1.101” ); 使用t

HBase在單Column和Column情況批量Put的性能對比分析

out amp .html 線程 its lse void 比較 操作 作者: 大圓那些事 | 文章可以轉載,請以超鏈接形式標明文章原始出處和作者信息 網址: http://www.cnblogs.com/panfeng412/archive/2013/11/28/hbas