2012-11-14 76 views
5

Sto disegnando il testo in una bitmap fuori campo della sezione DIB, che è profonda 32 bit e utilizza il canale alfa (ARGB). Disegno i pixel direttamente nella memoria. Quindi, creo un oggetto Gdiplus Graphics, mi trasferisco la memoria DC e disegno il testo usando Graphics :: DrawString. Funziona bene in circostanze normali. Su Remote Desktop, tuttavia, il rendering del testo è completamente trasparente, cioè, invece di disegnare qualsiasi pixel di colore, è possibile vedere attraverso il punto in cui si trova il testo. Qualcuno sa perché è così, e come ripararlo ??Gdiplus DrawString disegna testo trasparente su Desktop remoto

Ecco la mia routine drawString:

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

Ed è così che ho creato il 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... 
    } 

Dopo aver disegnato il testo nella DIB, faccio

gfx.Flush (Gdiplus::FlushIntentionSync); 

EDIT: potrebbe anche essere interessante per te che la finestra in cui il DIB viene infine inserito è una finestra WS_EX_LAYERED. Si tratta di una schermata iniziale che mostra quando si avvia l'applicazione, e si sta lentamente sbiadito dentro e fuori con un timer e il seguente metodo:

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

Cosa succede quando si modifica l'impostazione della profondità del colore della sessione RDP? –

+0

Ho testato 15 bit, 16 bit, 24 bit, 32 bit (impostazione nella scheda Visualizzazione prima dell'avvio della sessione RDP). Lo stesso problema con tutte queste impostazioni. (In realtà, 32 bit non mi sembra a 32 bit Forse l'RDP sta barando?) –

+0

Che ne dici di disabilitare la cache persistente di Bitmap? –

risposta

3

Mi sorprende questo funziona sempre. Disegnare con gdi32 perde le informazioni alfa e, a quanto ho capito, qualsiasi disegno su DIB a 32 bit con gdi32 lascia le informazioni alfa nel DIB undefined. GDI + deve passare attraverso gdi32 in questo caso perché gli hai dato un HDC.

Per disegnare a un RGBA DIB utilizzando GDI +, è necessario creare un oggetto GDI + Bitmap sostenuta dalla memoria del DIB con il formato di pixel corretto (utilizzando un costruttore che prende un puntatore di dati di pixel, come ad esempio this one), quindi create a Graphics object from your Bitmap. Ciò consente a GDI + di disegnare direttamente nella memoria DIB e gestire correttamente il canale alfa piuttosto che passare attraverso gdi32.

Ovviamente, se non è necessario alpha per pixel, è possibile semplificare le cose utilizzando un AlphaFormat di 0 nella funzione di fusione per ignorare il canale alfa nel DIB.

+0

Questa potrebbe essere la risposta, ma dal momento che sto facendo questo solo per la schermata Splash all'avvio dell'applicazione, ho "risolto" il problema semplicemente rilevando se l'applicazione è in esecuzione su Desktop remoto e, in caso affermativo, non mostrando la schermata Splash a tutti ... Economico, lo so. –

0

Ho una soluzione possibile per voi. Non sei sicuro di quale versione di Windows ti stai collegando, ma sul computer remoto potresti dover abilitare la modalità colore a 32 bit per i servizi terminal. In caso contrario, il client potrebbe essere limitato alla modalità a 16 bit.

Sul server, utilizzando gpedit.msc, configurare l'opzione "Limita profondità colore massima" su 32 bit. In Windows 2008/2012 questo è in Modelli amministrativi - Componenti di Windows - Servizi Desktop remoto - Ambiente sessione remota.

Se ci si connette a computer Windows XP/Vista/7/8, non sono sicuro che questa impostazione di gpedit sia disponibile.

+0

Ovviamente non posso farlo, perché non sono l'unico utente della nostra applicazione. Non posso aspettarmi che gli utenti possano modificare le loro impostazioni in Desktop remoto. Piuttosto, l'applicazione deve funzionare in entrambi gli ambienti. –