2012-11-14 14 views
5

Ich zeichne Text in eine DIB-Ausschnitt-Bitmap, die 32bit tief ist und den Alpha-Kanal (ARGB) verwendet. Ich zeichne Pixel direkt in den Speicher. Dann erstelle ich ein Gdiplus Graphics-Objekt, übermittle meinen Speicher DC daran und zeichne Text mit Graphics :: DrawString. Dies funktioniert unter normalen Umständen gut. Über Remote Desktop ist der gerenderte Text jedoch vollständig transparent, d. H., Anstatt irgendwelche Farbpixel zu zeichnen, können Sie sehen, wo der Text ist. Weiß jemand, warum das so ist und wie man es repariert?Gdiplus DrawString zeichnet transparenten Text über Remotedesktop

Hier ist meine drawString Routine:

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; 
    } 

Und das ist, wie ich die DIB erstellen:

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... 
    } 

Nach dem Zeichnen Text in die DIB, ich

gfx.Flush (Gdiplus::FlushIntentionSync); 

EDIT: Es Es könnte auch für Sie interessant sein, dass das Fenster, in das die DIB schließlich gezeichnet wird, ein WS_EX_LAYERED-Fenster ist. Es ist ein Splash-Screen, das zeigt, wenn die Anwendung gestartet wird, und wird in und aus mit einem Timer und die folgenden Methode langsam verblasst:

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

Was passiert, wenn Sie die Farbtiefe der RDP-Sitzung ändern? –

+0

Ich habe 15bit, 16bit, 24bit, 32bit getestet (Einstellung auf der Registerkarte Anzeige, bevor die RDP-Sitzung gestartet wird). Das gleiche Problem mit all diesen Einstellungen. (Eigentlich sieht 32bit nicht 32bit zu mir. Vielleicht rügt RDP?) –

+0

Wie wäre es mit Deaktivieren der dauerhaften Bitmap Caching? –

Antwort

3

Ich bin überrascht, das jemals funktioniert. Das Zeichnen mit gdi32 verliert Alpha-Informationen, und wie ich es verstehe, lässt jede Zeichnung auf einer 32-Bit-DIB mit gdi32 die Alpha-Information in der DIB undefiniert. GDI + muss in diesem Fall gdi32 durchlaufen, weil Sie ihm einen HDC gegeben haben.

zu einer RGBA-DIB zeichnen GDI +, müssen Sie von Ihrer DIB Speicher gesichert mit dem richtigen Bildformat (unter Verwendung einen Konstruktor, der einen Pixeldatenzeiger, wie this one nimmt), dann create a Graphics object from your Bitmap ein GDI + Bitmap-Objekt erstellen. Dadurch kann GDI + direkt in den Speicher des DIB zeichnen und den Alphakanal korrekt verarbeiten, anstatt gdi32 zu durchlaufen.

Natürlich, wenn Sie nicht pro-Pixel-Alpha benötigen, können Sie Dinge vereinfachen, indem Sie ein AlphaFormat 0 in Ihrer Blend-Funktion verwenden, um den Alpha-Kanal in Ihrer DIB zu ignorieren.

+0

Dies könnte die Antwort sein, aber da ich dies nur für den Splash-Bildschirm beim Start der Anwendung mache, "löste" ich das Problem, indem einfach festgestellt wurde, ob die Anwendung unter Remote Desktop ausgeführt wird, und wenn nicht, wird der Begrüßungsbildschirm angezeigt überhaupt ... Billig, ich weiß. –

0

Ich habe eine mögliche Lösung für Sie. Nicht sicher, mit welcher Windows-Version Sie eine Verbindung herstellen, aber auf dem Remote-Computer müssen Sie möglicherweise den 32-Bit-Farbmodus für Terminaldienste aktivieren. Andernfalls ist Ihr Client möglicherweise auf den 16-Bit-Modus beschränkt.

Konfigurieren Sie auf dem Server mit gpedit.msc die Option "Maximale Farbtiefe begrenzen" auf 32 Bit. In Windows 2008/2012 befindet sich dies in Administrative Vorlagen - Windows-Komponenten - Remotedesktopdienste - Remotesitzungsumgebung.

Wenn Sie eine Verbindung zu Windows XP/Vista/7/8 Computer herstellen, bin ich nicht sicher, ob diese gpedit Einstellung verfügbar ist.

+0

Natürlich kann ich das nicht, weil ich nicht der einzige Nutzer unserer Anwendung bin. Ich kann nicht erwarten, dass Benutzer ihre Einstellungen in Remotedesktop ändern. Vielmehr muss die Anwendung in beiden Umgebungen funktionieren. –