Przeźroczysto okno a odświeanie

0

Witam,

Mam problem, stworzyłem sobie przeźroczyste okno które wypisuje mi na pulpicie teksty, rysuje figury itd. Ale problem pojawia się gdy dane w oknie chcę zacząć często odświeżać np co sekundę. Niby znalazłem sposób ale powoduje on miganie okna co mnie nie satysfakcjonuje a gdy to usunąłem powróciłem do zabazgrawywania liter przez litery. Macie może pomysł jak te okno wyczyścić w taki sposób aby podczas odświeżania nie było mignięć??
Szukałem wiedzy w googlach, znalazłem coś o UpdateLayedWindow, ale albo nie działało albo nieumiejętnie tego używałem.

Mój kod:

#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <string>
#include <shellapi.h>
#include <string>
#include <objbase.h>
#include <assert.h>
#include <stdio.h>

#define WM_NOTIFYICONDATA	WM_APP + 300
#define IDT_DUE_TIME		1
#define IDT_UPDATE_INTERVAL	2
#define ID_MENU_EXIT 40001

typedef struct _INFO
{
	UINT uUpdateInterval;
	UINT uDueTime;
	char szText[255];
}INFO;

class COsdWnd
{
public:
	COsdWnd() : m_lpszClassName("3B07B496-C8BE-40a4-997C-061996F81F9F")
	{
		CoInitialize(NULL);

		m_bRegistered = FALSE;
		m_hFont = NULL;
		m_hWnd = NULL;
	}

	~COsdWnd()
	{
		if(m_bRegistered)
			UnregisterClass(m_lpszClassName, m_hInstance);

		if(m_hFont)
			DeleteObject(m_hFont);

		CoUninitialize();
	}

	BOOL Initialize(HINSTANCE hInstance)
	{
	    lol = 0;
		m_hInstance = hInstance;

		HDC hDC = GetDC(NULL);
		int nHeight = MulDiv(-18, GetDeviceCaps(hDC, LOGPIXELSY), 72);
		ReleaseDC(NULL, hDC);

		m_hFont = CreateFont(nHeight, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, NONANTIALIASED_QUALITY, DEFAULT_PITCH, "Verdana");
		if(!m_hFont)
			return FALSE;

		WNDCLASSEX wcl = {NULL};
		wcl.cbSize = sizeof(WNDCLASSEX);
		wcl.hInstance = m_hInstance;
		wcl.lpfnWndProc = (WNDPROC)WndProc;
		wcl.style = CS_HREDRAW | CS_VREDRAW;
		wcl.hIcon = LoadIcon(m_hInstance, IDC_ARROW);
		wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
		wcl.hbrBackground = (HBRUSH)GetStockObject(HOLLOW_BRUSH);
		wcl.lpszClassName = m_lpszClassName;
		if(!RegisterClassEx(&wcl))
			return FALSE;

		m_bRegistered = TRUE;

		HWND hWndDesktop = GetDesktopWindow();

		RECT rcClient;
		if(!GetClientRect(hWndDesktop, &rcClient))
			return FALSE;

		m_hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT, m_lpszClassName, NULL, WS_VISIBLE | WS_POPUP, 0, 0, 800, 80, hWndDesktop, NULL, m_hInstance, this);
		if(!m_hWnd)
			return FALSE;

		return TRUE;
	}

	void DoModal()
	{
		assert(IsWindow(m_hWnd));

		ShowWindow(m_hWnd, SW_SHOW);
		UpdateWindow(m_hWnd);
		SetLayeredWindowAttributes(m_hWnd, 0, 0, LWA_COLORKEY);

		MSG msg;
		while(GetMessage(&msg, NULL, 0, 0))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

private:
	static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
	{
		static COsdWnd *pThis = NULL;
		if(uMessage == WM_CREATE)
			pThis = (COsdWnd *)((CREATESTRUCT *)(lParam))->lpCreateParams;

		return pThis->WindowProc(hWnd, uMessage, wParam, lParam);
	}

	LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
	{
		switch(uMessage)
		{
		case WM_COMMAND:
			if(LOWORD(wParam) == ID_MENU_EXIT)
				DestroyWindow(hWnd);
			else
				return DefWindowProc(hWnd, uMessage, wParam, lParam);
			break;

		case WM_CREATE:
			SetTimer(hWnd, IDT_UPDATE_INTERVAL, 1000, NULL);
			break;

		case WM_DESTROY:
			KillTimer(hWnd, IDT_DUE_TIME);
			KillTimer(hWnd, IDT_UPDATE_INTERVAL);

			PostQuitMessage(0);
			break;

		case WM_PAINT:
			if(m_strText.empty())
				return DefWindowProc(hWnd, uMessage, wParam, lParam);

			OnPaint();
			break;

		case WM_TIMER:
			if(wParam == IDT_DUE_TIME)
			{
				KillTimer(hWnd, IDT_DUE_TIME);
				SetTimer(hWnd, IDT_UPDATE_INTERVAL, 1000, NULL);
			}
			else if(wParam == IDT_UPDATE_INTERVAL && GetLatestArticles())
			{
				InvalidateRect(hWnd, NULL, TRUE);
				KillTimer(hWnd, IDT_UPDATE_INTERVAL);
				SetTimer(hWnd, IDT_DUE_TIME, 1000, NULL);
			}
			break;

		default:
			return DefWindowProc(hWnd, uMessage, wParam, lParam);
		}

		return 0;
	}

	void OnPaint()
	{
		PAINTSTRUCT ps = {NULL};
		HDC hDC = BeginPaint(m_hWnd, &ps);
		SetTextColor(hDC, RGB(0, 255, 0));
		SetBkMode(hDC, TRANSPARENT);
		SelectObject(hDC, m_hFont);
		RECT rc;
		GetClientRect(m_hWnd, &rc);
		rc.left += 10;
		rc.top += 10;
		DrawText(hDC, m_strText.c_str(), m_strText.length(), &rc, DT_LEFT);
		EndPaint(m_hWnd, &ps);
	}

	BOOL GetLatestArticles()
	{
		try
		{
			m_strText.erase();
            char buf[1024];
            lol++;
            sprintf(buf, "%i", lol);
			m_strText.append(buf);
		}
		catch(...)
		{
			return FALSE;
		}

		return TRUE;
	}

private:
	HINSTANCE		m_hInstance;
	HWND			m_hWnd;
	LPCTSTR			m_lpszClassName;
	HFONT			m_hFont;
	std::string		m_strText;
	BOOL			m_bRegistered;
	int lol;
};

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	COsdWnd wnd;
	if(!wnd.Initialize(hInstance))
		return -1;

	wnd.DoModal();
	return 0;
}

Dzięki za pomoc.
Pozdrawiam.

0

InvalidateRect(hWnd, NULL, TRUE);
Powinieneś odmalować jak najmniejszy obszar, a nie wszystko na raz. Przezroczyste okna nie są zbyt wydajne.

0

Chyba wiem jak powinieneś to zrobić, jednak nie będzie to zbyt wydajne :). Pobierasz współrzędne kontrolki statica czy jakiejś, zamieniasz je do współrzędnych globalnych i pobierasz kawałek pulpitu znajdujący się dokładnie pod tą kontrolką. Zachowujesz to jako HBITMAP z którego tworzysz PatternBrush który będzie zwracany w obsłudze komunikatu WM_CTLCOLORSTATIC. Stosuje ten myk jak potrzebuje przezroczystego statica, który wyświetla dynamiczny napis(problem był ten co u Ciebie - litery nachodziły na siebie). W moim przypadku pobieralem tło okna głównego, a Twoim jak rozumiem jest pulpit ;). Jeżeli z wykonaniem będziesz miał problem to pisz.

0

generalnie tak Tyle, że chodzi o ten myk, że te prawdziwe przezrocze przepuszcza sygnały do okien pod nim, a to(chyba?) nie, pisze taką nakładę na grę, dodatkowe szczegółowe informacje, trochę nowego interfejsu więc potrzeba mi to rozwiązać jakoś "bardzo przezroczyście" ^^

0

Hmm, ja kiedyś szukałem długi czas rozwiązania tego problemu i jedyne co znalazłem to właśnie tworzenie patternbrusha... wydaje mi się, że to jedyna opcja też w Twoim wypadku. Tyle, że Ty będziesz musiał co sekundę(za każdym odświeżeniem) pobrać od nowa skrawek okna gry znajdujący się pod kontrolką, bo tło będzie dynamiczne. To, że Twoje przepuszcza komunikaty nie ma znaczenia w tym wypadku, okno to okno tak mi się wydaje. Wieczorem jak nie zapomnę to sprawdzę moją teorię z ciekawości ;P

1 użytkowników online, w tym zalogowanych: 0, gości: 1