2012-11-14 11 views
5

Rysuję tekst w sekcji DIB poza bitmapą o rozdzielczości 32 bitów i używa kanału alfa (ARGB). Rysuję piksele bezpośrednio w pamięci. Następnie tworzę obiekt Gdiplus Graphics, przekazuję do niego pamięć DC i rysuję tekst za pomocą Graphics :: DrawString. Działa to dobrze w normalnych warunkach. Jednak w przypadku pulpitu zdalnego renderowany tekst jest całkowicie przezroczysty, tzn. Zamiast rysowania dowolnych kolorowych pikseli można zobaczyć, gdzie znajduje się tekst. Czy ktoś wie, dlaczego tak jest i jak to naprawić?Metoda GdPlus DrawString rysuje przezroczysty tekst na pulpicie zdalnego sterowania

Oto mój sznurkiem rutyna:

void SplashScreen::drawString (MyString &ivText, Gdiplus::RectF &r, 
    Gdiplus::ARGB c, Gdiplus::StringAlignment align, Gdiplus::Font &fnt, 
    Gdiplus::Graphics &gfx) 
    { 
    Gdiplus::StringFormat fmt; 
    fmt.SetAlignment (align); 
    Gdiplus::SolidBrush brush (c); 
    wchar_t *wstr = new wchar_t [ivText.length()+1]; 
    std::mbstowcs (wstr, ivText.cstr(), ivText.length()+1); 
    gfx.DrawString (wstr, ivText.length(), &fnt, r, &fmt, &brush); 
    delete wstr; 
    } 

I tak jak ja stworzyć DIB:

BITMAPV5HEADER bhd; 
memset (&bhd, 0, sizeof (bhd)); 
bhd.bV5Size = sizeof (BITMAPV5HEADER); 
bhd.bV5Width = nWidth; 
bhd.bV5Height = -nHeight; // negative height indicates top-down DIB 
bhd.bV5Planes = 1; 
bhd.bV5BitCount = 32; 
bhd.bV5Compression = BI_BITFIELDS; 
bhd.bV5RedMask = 0x00FF0000; 
bhd.bV5GreenMask = 0x0000FF00; 
bhd.bV5BlueMask = 0x000000FF; 
bhd.bV5AlphaMask = 0xFF000000; 
m_pBuf = NULL; 
m_hBmp = ::CreateDIBSection (m_hDC, (BITMAPINFO *) &bhd, DIB_RGB_COLORS, 
    (void **) &m_pBuf, NULL, 0); 
if (m_hBmp == NULL || m_pBuf == NULL) 
    { 
    // error... 
    } 
HGDIOBJ oldObj = ::SelectObject (m_hDC, m_hBmp); 
if (oldObj == NULL) 
    { 
    // error... 
    } 

Po narysowaniu tekstu do DIB, robię

gfx.Flush (Gdiplus::FlushIntentionSync); 

EDIT: Jest może cię również zainteresować, że okno, w którym DIB jest ostatecznie wciągnięte, jest oknem WS_EX_LAYERED. Jest to ekran powitalny, który pokazuje podczas uruchamiania aplikacji i powoli wyblakłe i obecnie przy użyciu timera i następujący sposób:

void SplashScreen::setWindowTransparency (int nAlpha) 
    // @param nAlpha: 255 is opaque, 0 is fully transparent. 
    { 
    HWND hwnd = getHwnd(); 
    BLENDFUNCTION blend; 
    blend.BlendOp = AC_SRC_OVER; 
    blend.BlendFlags = 0; 
    blend.SourceConstantAlpha = nAlpha; 
    blend.AlphaFormat = AC_SRC_ALPHA; 
    BOOL bResult = ::UpdateLayeredWindow (hwnd, NULL, NULL, NULL, NULL, 
    NULL, RGB (0, 0, 0), &blend, ULW_ALPHA); 
    } 
+0

Co się stanie, gdy zmienisz ustawienie głębi kolorów sesji RDP? –

+0

Przetestowałem 15-bit, 16-bit, 24-bit, 32-bitowy (ustawienie w zakładce Wyświetlanie przed uruchomieniem sesji RDP). Ten sam problem z wszystkimi tymi ustawieniami. (Właściwie 32-bit nie wygląda na 32-bity, może RDP oszukuje?) –

+0

Co powiesz na wyłączenie Trwałego buforowania bitmap? –

Odpowiedz

3

Dziwię się to kiedykolwiek działa. Rysowanie za pomocą gdi32 powoduje utratę informacji alfa i jak rozumiem, każdy rysunek na 32-bitowym DIB z gdi32 pozostawia niezdefiniowaną informację alfa w DIB. GDI + musi przejść przez gdi32 w tym przypadku, ponieważ dałeś mu HDC.

Aby narysować na RGBA DIB użyciu GDI +, trzeba stworzyć GDI + Bitmap obiekt poparte pamięci DIB jest z prawidłowym formacie pikseli (przy użyciu konstruktora, że ​​trwa wskaźnik danych pikseli, takich jak this one), a następnie create a Graphics object from your Bitmap. Pozwala to GDI + narysować bezpośrednio do pamięci DIB i poprawnie obsłużyć kanał alfa, a nie przejść przez gdi32.

Oczywiście, jeśli nie potrzebujesz alfa w pikselach, możesz uprościć rzeczy, używając funkcji AlphaFormat równej 0 w funkcji mieszania, aby zignorować kanał alfa w swoim DIB.

+0

To może być odpowiedź, ale ponieważ robię to tylko dla ekranu powitalnego podczas uruchamiania aplikacji, "rozwiązałem" problem, po prostu wykrywając, czy aplikacja działa pod Pulpitem zdalnym, a jeśli tak, nie pokazując ekranu powitalnego w ogóle ... Tani, wiem. –

0

Mam dla ciebie możliwe rozwiązanie. Nie masz pewności, z którą wersją systemu Windows się łączysz, ale na komputerze zdalnym może być konieczne włączenie 32-bitowego trybu koloru dla usług terminalowych. W przeciwnym razie twój klient może być ograniczony do trybu 16-bitowego.

Na serwerze, używając gpedit.msc, skonfiguruj opcję "Ogranicz maksymalną głębię kolorów" do 32 bitów. W systemie Windows 2008/2012 jest to w szablonach administracyjnych - składniki systemu Windows - usługi pulpitu zdalnego - środowisko sesji zdalnej.

Jeśli łączysz się z komputerem z systemem Windows XP/Vista/7/8, nie jestem pewien, czy to ustawienie gpedit jest dostępne.

+0

Oczywiście nie mogę tego zrobić, ponieważ nie jestem jedynym użytkownikiem naszej aplikacji. Nie mogę oczekiwać, że użytkownicy będą zmieniać swoje ustawienia w Pulpicie zdalnym. Zamiast tego aplikacja musi działać w dowolnym środowisku. –