bild auf dem desktop ausgeben



  • du kannst ja dein fenster unsichtbar machen und dann auf den desktop malen

    also mit GetDC(NULL) bekommst du den desktop und da dann einfach ne bmp drauf zeichnen



  • Moin, Moin...

    Als Beispiel, wie man auf den Desktop rummalt, poste ich hier ein kleines Programm aus dem Petzold:

    /*------------------------------------------------
       SCRAMBLE.C -- Scramble (and Unscramble) Screen
                     (c) Charles Petzold, 1998
      ------------------------------------------------*/
    
    #include <windows.h>
    
    #define NUM 300
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow)
    {
         static int iKeep [NUM][4] ;
         HDC        hdcScr, hdcMem ;
         int        cx, cy ;
         HBITMAP    hBitmap ;
         HWND       hwnd ;
         int        i, j, x1, y1, x2, y2 ;
    
         if (LockWindowUpdate (hwnd = GetDesktopWindow ()))
         {
              hdcScr  = GetDCEx (hwnd, NULL, DCX_CACHE | DCX_LOCKWINDOWUPDATE) ;
              hdcMem  = CreateCompatibleDC (hdcScr) ;
              cx      = GetSystemMetrics (SM_CXSCREEN) / 10 ;
              cy      = GetSystemMetrics (SM_CYSCREEN) / 10 ;
              hBitmap = CreateCompatibleBitmap (hdcScr, cx, cy) ;
    
              SelectObject (hdcMem, hBitmap) ;
    
              srand ((int) GetCurrentTime ()) ;
    
              for (i = 0 ; i < 2   ; i++)
              for (j = 0 ; j < NUM ; j++)
              {
                   if (i == 0)
                   {
                        iKeep [j] [0] = x1 = cx * (rand () % 10) ;
                        iKeep [j] [1] = y1 = cy * (rand () % 10) ;
    
                        iKeep [j] [2] = x2 = cx * (rand () % 10) ;
                        iKeep [j] [3] = y2 = cy * (rand () % 10) ;
                   }
                   else
                   {
                        x1 = iKeep [NUM - 1 - j] [0] ;
                        y1 = iKeep [NUM - 1 - j] [1] ;
                        x2 = iKeep [NUM - 1 - j] [2] ;
                        y2 = iKeep [NUM - 1 - j] [3] ;
                   }
                   BitBlt (hdcMem,  0,  0, cx, cy, hdcScr, x1, y1, SRCCOPY) ;
                   BitBlt (hdcScr, x1, y1, cx, cy, hdcScr, x2, y2, SRCCOPY) ;
                   BitBlt (hdcScr, x2, y2, cx, cy, hdcMem,  0,  0, SRCCOPY) ;
    
                   Sleep (10) ;
              }
    
              DeleteDC (hdcMem) ;
              ReleaseDC (hwnd, hdcScr) ;
              DeleteObject (hBitmap) ;
    
              LockWindowUpdate (NULL) ;
         }
         return FALSE ;
    }
    

    Es zeigt, wie man das Handle für den Desktop erhält und den Desktop sperrt(!!) bevor man darauf rummalt.

    Ciao....



  • Wenn man z.b. auf dem Desktop ein Bild anzeigen will, dass immer im vordergrund bleibt, also auch wenn ein Fenster darübergemalt wird, müsste man ja sozusagen die WM_PAINT nachricht für den desktop mitbekommmen. gibt es die überhaupt? und wie fängt man sie ab?



  • Wenn es auch über allen Fenstern liegen soll, dann wäre es ja nich mehr auf dem Desktop (denn der wird ja von Fenstern überdeckt) 😕



  • stimmt..hab mal wieder nicht nachgedacht.
    Allerdings wäre folgendes auch ganz interessant:
    wie kann man text immer im vordergrund anzeigen, also immer in dem fenster, das sich momentan an dieser stelle befindet.
    aber das nur nebenbei...
    was ich meinte ist folgendes:
    wie finde ich heraus, dass ein fenster gerade verkleinert wurde, also der desktop neu gezeichnet werden muss, und man sozusagen seinen text wieder drüberschreiben muss?



  • Warum nimmst du nicht ein eigenes Fenster und platzierst es mit HWND_BOTTOM bzw. HWND_TOPMOST 🙄
    Ansonsten müsstest du wohl mit Sub-Classing arbeiten oder das ganze einfach als Desktop-Hintergrundbild machen 🙂



  • McFarmer schrieb:

    ...
    wie finde ich heraus, dass ein fenster gerade verkleinert wurde, also der desktop neu gezeichnet werden muss, und man sozusagen seinen text wieder drüberschreiben muss?

    Stichwort: Hook

    HHOOK SetWindowsHookEx(
    
        int idHook,	// "WH_CALLWNDPROCRET"  Hooktyp der Installiert wird
        HOOKPROC lpfn,	// Adresse zur Hookprocedure
        HINSTANCE hMod,	// HInstance des Programms
        DWORD dwThreadId 	// 0=alle oder halt entsprechende id
       );
    //-----
    LRESULT CALLBACK CallWndRetProc(
    
        int nCode,	// Hookcode (siehe MSDN WH_)
        WPARAM wParam,	// kennste
        LPARAM lParam 	// kennste auch
       );
    

    Nachrichten abfangen nachdem die Clienten die Nachricht erhalten haben.
    Auswerten und neuzeichnen.

    *****************

    Wenn du sowas wie OSD realisieren willst, also Text einblenden und später wieder aus.
    reicht folgendes:

    Text einblenden:

    char Text[] = "OSD Anzeige"; 
                     HDC dc = GetDC(NULL);
                     HFONT hFont = CreateFont(36,0,0,0,700,0,0,0,0,0,0,0,FIXED_PITCH,"Arial");
                     HGDIOBJ OldObject = SelectObject(dc,hFont);
                     SetBkMode(dc,TRANSPARENT);
                     SetTextColor(dc,RGB(0,0,0)); // schwarzer Rand
                     TextOut(dc, 41, 51, Text, strlen(Text)); // für Rand
                     TextOut(dc, 39, 51, Text, strlen(Text)); // dito
                     TextOut(dc, 41, 49, Text, strlen(Text)); // dito
                     TextOut(dc, 39, 49, Text, strlen(Text)); // dito
                     SetTextColor(dc,RGB(255,255,0)); // Textfarbe
                     TextOut(dc, 40, 50, Text, strlen(Text));
                     SelectObject(dc, OldObject);
                     ReleaseDC(NULL,dc);
    

    Ausblenden:

    RECT rc; 
                     rc.left = 35;
                     rc.right = 250;
                     rc.top = 40;
                     rc.bottom = 100;
                     RedrawWindow(NULL,&rc,NULL,RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
    

    Wenn das Einblenden über längere Zeit statt finden soll, lass es in einer schleife

    Pseudocode:

    while (an) {
        /* PeekMessage() schleife um Nachrichten zu Verarbeiten */
        ClearDesktop() // Das Ausblenden (RedrawWindow() )
        CaptureDesktop() // GetDC(NULL) und in eine Bitmap blitten
        TextOutBitmap() // Text in Bitmap
        DrawBitmap() // Backbuffer Bitmap auf Desktop zeichnen
    }
    


  • Äh, help please:

    //hier passier der Fehler. Warum gehts net ?
    HDC dc = GetDC(NULL);

    error C2660: 'CWnd::GetDC': Funktion akzeptiert keine 1 Argumente



  • Hast du es in deinem Code auch so geschrieben wie hier, den so ist es Richtig.



  • Hallo,
    ja genau so hab ich es auch übernommen.
    Hab ich vergessen was zu includen ?
    Bekomme den Fehler wie beschrieben und bei

    ReleaseDC(NULL,dc);
    error C2660: 'CWnd::ReleaseDC': Funktion akzeptiert keine 2 Argumente
    😕



  • Entschuldigt, hat sich erledigt!

    ::GetDC(NULL)
    ::ReleaseDC(NULL,dc);



  • Ist aber Merkwürdig das du ::Funktion schreiben muß, kann es sein das du was includet hast was nicht notwendig ist?



  • Keine Ahnung. Hab sonst nichts weiter gemacht.
    Wollte nur mal den Code testen weil ich es
    sehr interessant fand. Komisch warum es nur
    so geht 😕 Aber vielen Dank 🙂



  • Du scheinst MFC zu verwenden - rufst du denn den Code innerhalb einer Klasse auf, oder hast du irgendwie ein using namespace o.ä. verwendet 😕


Anmelden zum Antworten