VBox 심리스모드 도우미

저만 그런가요.
VirtualBox에서 심리스모드로 들어가면
창이 아무것도 없을 때 바탕화면이 드러나면서 제대로 심리스가 안되더군요.
그런데 창이 하나라도 떠있으면 제대로 됩니다. (시작 메뉴만 눌러도 정상)

그래서 작은 창을 띄워주는 프로그램을 하나 만들었습니다.
[attachment=1:1wgtm80k]VBoxToy.png[/attachment:1wgtm80k]
'시작 프로그램’에 넣어주면 부팅될 때 자동 실행되서 왼쪽 상단에 뜨게 만들었습니다.
아이콘 위에서 마우스 가운데 버튼을 눌러주면 전체로 확대되서 바탕화면을 잠깐 확인할 수 있습니다.

그냥 그게 답니다.
시스템 리소스 거의 안 먹습니다.

마음껏 수정 & 배포 가능합니다.
[attachment=0:1wgtm80k]VBoxToy.7z[/attachment:1wgtm80k]

만약 저만 심리스모드가 그런 거라면… 그저 지나가는 삽질일뿐… 꿈틀꿈틀…

소스도 올립니다.

VC++ 6.0에서 작업했습니다.

[code:1274yzok]#include "stdafx.h"
#include "resource.h"

#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 0x00000001
#define LWA_ALPHA 0x00000002
#define ULW_COLORKEY 0x00000001
#define ULW_ALPHA 0x00000002
#define ULW_OPAQUE 0x00000004
typedef BOOL (WINAPI* pSLWA)(HWND, COLORREF, BYTE, DWORD);
pSLWA pSetLayeredWindowAttributes = NULL;

#define APP_NAME "VirtualBox Toy"
#define APP_CLASS "VBoxToy"
HWND g_hMainWnd = NULL;
HICON g_hMainIcon = NULL;
HICON g_hSmallIcon = NULL;
HICON g_hBigIcon = NULL;
BOOL g_bMax = FALSE;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
g_hMainIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_VBOX));
g_hSmallIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_VBOX), IMAGE_ICON, 16, 16, 0);
g_hBigIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_VBOX), IMAGE_ICON, 64, 64, 0);

// 윈도우 클래스 등록
WNDCLASS xClass;
xClass.style = NULL;
xClass.lpfnWndProc = WndProc;
xClass.cbClsExtra = 0;
xClass.cbWndExtra = 0;
xClass.hInstance = hInstance;
xClass.hIcon = g_hMainIcon;
xClass.hCursor = LoadCursor(NULL, IDC_ARROW);
xClass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
xClass.lpszMenuName = NULL;
xClass.lpszClassName = APP_CLASS;
if (RegisterClass(&xClass) == 0)
	return -1;

// 윈도우 생성
g_hMainWnd = CreateWindow(
	TEXT(APP_CLASS), TEXT(APP_NAME),
	WS_POPUP | WS_BORDER | WS_SYSMENU,
	0, 0, 1, 1,
	NULL, NULL,
	hInstance, 0
);
if (g_hMainWnd == NULL)
	return -1;

// 윈도우 속성 변경
LONG nExStyle = GetWindowLong(g_hMainWnd, GWL_EXSTYLE);
nExStyle &= ~WS_EX_APPWINDOW;
nExStyle |= WS_EX_TOOLWINDOW;
nExStyle |= WS_EX_LAYERED;
SetWindowLong(g_hMainWnd, GWL_EXSTYLE, nExStyle);
HINSTANCE hmodUSER32 = LoadLibrary("USER32.DLL");
pSetLayeredWindowAttributes = (pSLWA)GetProcAddress(hmodUSER32, "SetLayeredWindowAttributes");
pSetLayeredWindowAttributes(g_hMainWnd, 0, 250, LWA_ALPHA);

RECT rt;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rt, 0);
SendMessage(g_hMainWnd, WM_SETICON, ICON_BIG, (LPARAM)g_hMainIcon);
SendMessage(g_hMainWnd, WM_SETICON, ICON_SMALL, (LPARAM)g_hSmallIcon);
SetWindowPos(g_hMainWnd, HWND_BOTTOM,
	rt.left, rt.top,
	64,64,
	SWP_NOACTIVATE
);

ShowWindow(g_hMainWnd, nCmdShow);
UpdateWindow(g_hMainWnd);

// 메인 쓰레드
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
	TranslateMessage(&msg);
	DispatchMessage(&msg);
}

return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
return FALSE;

case WM_PAINT:
	{
		HDC hdc;
		PAINTSTRUCT ps;
		RECT rt;

		GetClientRect(hWnd, &rt);
		hdc = BeginPaint(hWnd, &ps);
		DrawIconEx(hdc,
			(rt.right - rt.left - 64) / 2, (rt.bottom - rt.top - 64) / 2,
			g_hBigIcon,
			64, 64,
			0, NULL,
			DI_NORMAL
		);
		EndPaint(hWnd, &ps);
	}
	return FALSE;

case WM_DESTROY :
	DestroyIcon(g_hBigIcon);
	DestroyIcon(g_hSmallIcon);
	DestroyIcon(g_hMainIcon);
	g_hBigIcon = NULL;
	g_hSmallIcon = NULL;
	g_hMainIcon = NULL;
	PostQuitMessage(0);
	return FALSE;

case WM_NCHITTEST:
	if (g_bMax == FALSE)
	{
		if ( (GetKeyState(VK_RBUTTON) & 0x8000) != 0
		  || (GetKeyState(VK_MBUTTON) & 0x8000) != 0 )
		  break;
		return HTCAPTION;
	}
	break;

case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
	if (g_bMax == TRUE)
	{
		ShowWindow(hWnd, SW_RESTORE);
		pSetLayeredWindowAttributes(g_hMainWnd, 0, 232, LWA_ALPHA);
		g_bMax = FALSE;
	}
	break;

case WM_MBUTTONUP:
	if (g_bMax == FALSE)
	{
		pSetLayeredWindowAttributes(g_hMainWnd, 0, 64, LWA_ALPHA);
		ShowWindow(hWnd, SW_MAXIMIZE);
		g_bMax = TRUE;
	}
	else
	{
		ShowWindow(hWnd, SW_RESTORE);
		pSetLayeredWindowAttributes(g_hMainWnd, 0, 232, LWA_ALPHA);
		g_bMax = FALSE;
	}
}
return DefWindowProc(hWnd, msg, wParam, lParam);

}
[/code:1274yzok]

저도 compiz를 사용할 때 비슷한 문제로 virtualbox 의 seamless를 한동한 사용하지 않다가,
이를 해결하기 위한 workaround 를 발견해서 썼었습니다.

http://www.fergytech.com/2008/10/virtua ... -w-compiz/

1x1 pixel 짜리 윈도우를 띄우는 거구요. 아마 같은 원리로 생각됩니다.

그런데, 어느 순간부터 이것도 필요가 없이 그냥 잘 되더군요.
(compiz 1:0.8.4-0ubuntu3~ppa1, virtualbox 3.1.2-56127_Ubuntu_karmic)

참고하시기 바랍니다.