如何用win32的函数调节设置Unity的窗口

4 篇文章 0 订阅

由于目前要做一个Unity的项目,在Win7系统上,要实现全屏功能,并且有聊天功能。做过的码农都知道,Win7系统上,全屏时输入法看不到选词。针对这个问题,我在网上google了一下,也结合之前做的东西,总算解决了这个问题。

其实道理很简单,既然全屏不能看到选词,那么就不全屏。但是窗口要铺满屏幕,并且将边框隐藏。

这个分两步走,我们直接贴代码,代码里有注释。首先是C#端:

using UnityEngine;
using System.Runtime.InteropServices;
using System;
using System.Collections;


public class SetUnityWindow : MonoBehaviour
{


    [DllImport("UnityWindowSet")]
    static extern MONITORRECT GetMonitorRect();


    [DllImport("UnityWindowSet")]
    static extern int SetWindowFullScreen(MONITORRECT rect);

      //这个属性告诉编译器,当把该结构传递给非托管编译的时候,按照我们定义的顺序排序,而不是单字节对齐或者怎样。
    [StructLayout(LayoutKind.Sequential)]
    struct MONITORRECT
    {
        public long left;
        public long top;
        public long right;
        public long bottom;
    }


    Vector2 screenRect;
    IEnumerator Start()
    {
        yield return new WaitForEndOfFrame();


        MONITORRECT monitorRect = GetMonitorRect();

        screenRect.x = monitorRect.right - monitorRect.left;
        screenRect.y = monitorRect.bottom - monitorRect.top;

	    SetWindowFullScreen(monitorRect);
    }
}

然后是C++端代码:

#include<Windows.h>
#include<vector>

using namespace std;

struct ALLMONITORINFO
{
	HMONITOR hMonitor;
	RECT     rect;
	bool     isPrimary;
};


//获取所有显示器信息的回调函数。
static 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;
} 


extern "C"
{
	__declspec(dllexport) RECT __stdcall GetMonitorRect()
	{
		//获取当前前景窗口的句柄。这句话很重要,获取到窗口句柄是我们后面所有工作的基础。只要我们会C++ Winform编程,就可以修改unity的窗口显示了。
		HWND hWin = GetForegroundWindow();
		HMONITOR hMonitor = MonitorFromWindow(hWin, MONITOR_DEFAULTTONEAREST);
		vector<ALLMONITORINFO> mInfo;
		mInfo.clear();


		EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, reinterpret_cast<LPARAM>(&mInfo));


		for (int i = 0; i < mInfo.size(); i++)
		{
			if (hMonitor == mInfo[i].hMonitor)
			{
				return mInfo[i].rect;
			}
		}


		return RECT();
	}


	__declspec(dllexport) BOOL __stdcall SetWindowFullScreen(RECT rect)
	{
		HWND hWindow = GetForegroundWindow();
		SetWindowLong(hWindow, GWL_STYLE, WS_POPUP);
		SetWindowPos(hWindow, 0, 0, 0, (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), SWP_SHOWWINDOW);
		
		return TRUE;
	}
}


其实在这个例子中,在C#端,我们可以精简到只调用一个C++函数。但是有一个现象,那就是我们自己定义的RECT结构竟然能跟C++的RECT结构互相使用。因为C++开发做得比较少,所以对这个现象比较吃惊。所以以后有类似情况时,我们可以按照C++的方式重新定义一个结构,只要字节对齐就可以了。

然后我们能修改Unity窗口的基础是GetForegroundWindow()函数,即获取当前前景窗口的句柄。然后如果有C++ Winform编程基础的话,就可以修改Unity窗口变成任何自己想要的样式了。这个函数也可以通过将user32.dll放到Unity的Plugins文件夹下,然后在C#中调用。

我们用C++写的这个dll有一个问题,那就是32位和64位的问题。一直想找个办法让一个dll既能兼容32位,又能兼容64位,就像user32.dll一样。但是无果。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值