Przeźroczysto okno a odświeanie

Odpowiedz Nowy wątek
2012-03-16 23:55
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.

edytowany 3x, ostatnio: Miziak, 2012-03-17 00:04

Pozostało 580 znaków

2012-03-17 08:17
0

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

edytowany 5x, ostatnio: adf88, 2012-03-17 08:31

Pozostało 580 znaków

2012-03-17 15:09
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.


non omnis moriar i tyle :-)

Pozostało 580 znaków

2012-03-17 22:59
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" ^^

Pozostało 580 znaków

2012-03-18 11:33
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


non omnis moriar i tyle :-)
edytowany 1x, ostatnio: arasso12, 2012-03-18 11:34

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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