首页 > 代码库 > 使用Unity3d做异形窗口
使用Unity3d做异形窗口
项目马上上线,因为之前的登录器是使用VS2010的MFC做的,在很多电脑上会提示缺失mfcXXXX.dll,中间找寻这种解决方案,最后确定将vcredist2010_x86和我的程序打包到安装包里面,每次安装的时候默认先安装vcredist2010_x86。
由此,经常被杀毒软件阻止,而且还有x64 or x86的区别。
同时,甲方想要一个精灵,类似于QQ宠物,于是PL决定使用精灵模型+异形窗口做一个桌面宠物。于是,异形窗口成了此物的基础。
首先,我们需要了解的是,异形窗口是什么。简单来说,即将窗口形状变成由一张不规则(一般由透明色决定)图片所决定的形状。
然后,需要知道的是窗口的形状是由什么决定。在MSDN上我发现,普通的窗口形状由一个简单的Rectangular Region决定。经查询之后,要实现异形窗口主要要靠这几个函数:
a. 创建一个矩形区域
?
1 2 3 4 5 6 7 | //The CreateRectRgn function creates a rectangular region. <br> HRGN CreateRectRgn( int nLeftRect, // x-coordinate of upper-left corner int nTopRect, // y-coordinate of upper-left corner int nRightRect, // x-coordinate of lower-right corner int nBottomRect // y-coordinate of lower-right corner ); |
b. 结合n个矩形区域
?
1 2 3 4 5 6 7 8 9 | //The CombineRgn function combines two regions and stores the result in a third region. //The two regions are combined according to the specified mode. int CombineRgn( HRGN hrgnDest, // handle to destination region HRGN hrgnSrc1, // handle to source region HRGN hrgnSrc2, // handle to source region int fnCombineMode // region combining mode ); |
c. 将窗口显示出来
?
1 2 3 4 5 6 7 8 9 | //The SetWindowRgn function sets the window region of a window. //The window region determines the area within the window where the system permits drawing. //The system does not display any portion of a window that lies outside of the window region int SetWindowRgn( HWND hWnd, // handle to window HRGN hRgn, // handle to region BOOL bRedraw // window redraw option ); |
d. 去掉窗口标题栏(主要窗口截图只能截到窗口边框内)
?
1 2 3 4 5 6 7 | //This function changes an attribute of the specified window. //SetWindowLong also sets a 32-bit (LONG) value at the specified offset into the extra window memory of a window.<br> LONG SetWindowLong( HWND hWnd, int nIndex, LONG dwNewLong ); |
最后,在unity里面调用user32.dll 和 Gdi32.dll 两个动态链接库,结合unity界面截图,得到最后的处理结果。贴上部分处理代码:
1 /// <summary> 2 /// use the screen shot image to cut the window. 3 /// </summary> 4 private void updateWindow() { 5 System.IntPtr hRgn = WinAPI.CreateRectRgn(0, 0, 0, 0); 6 7 Debug.Log(" width: " + winTex2d.width + " height: " + winTex2d.height); 8 9 for (int h = 0; h < winTex2d.height; ++h) {//int h = tex2d.height - 1; h > tex2d.height/2; --h 10 //Debug.Log(tex2d.GetPixel(h, h)); 11 int w = 0; 12 do { 13 while (w < winTex2d.width && (winTex2d.GetPixel(w, winTex2d.height - h) == Color.clear 14 || winTex2d.GetPixel(w, h) == Color.black 15 )) { 16 ++w; 17 //Debug.Log(tex2d.GetPixel(w, h)); 18 } 19 int iLeftX = w; 20 while (w < winTex2d.width && (winTex2d.GetPixel(w, winTex2d.height - h) != Color.clear 21 //|| tex2d.GetPixel(w, h) != Color.black 22 )) { 23 ++w; 24 //Debug.Log(tex2d.GetPixel(w, h)); 25 } 26 //Debug.Log("ileftX: " + iLeftX + "w: " + w + h); 27 28 WinAPI.CombineRgn(hRgn, hRgn, WinAPI.CreateRectRgn(iLeftX, h, w, h + 1), 2); 29 }//end do{} 30 while (w < winTex2d.width); 31 }//end for(h); 32 33 Debug.Log("setWindowRgn: " + WinAPI.SetWindowRgn(WinAPI.GetActiveWindow(), hRgn, true)); 34 }//end updateWindow();
PS:这种处理方式当图形透明区域特别多的时候,会出现整个处理过程有些卡顿,后期可能要加入线程进行处理。
感谢您的阅读,如果您有好的建议,望不吝赐教!
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。