Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

31.08.2006, 13:04

Bitmap als Hintergrund

hi,

ich habe mit folgendem Programm eine Bitmap als Hintergrund, die immer gekachelt wird:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include "main.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND        hwnd;               // Fensterhandle

    MSG         msg;                // Variable für die Fenster-Messages

    WNDCLASSEX  wnd_class;          // Struktur beinhaltet die Fensterattribute

    LOGBRUSH    background;         // Logical Brush, der den Hintergrund beinhaltet


    wnd_class.cbSize            = sizeof(wnd_class);                // Größe der Klasse

    wnd_class.style             = CS_HREDRAW | CS_VREDRAW;          // Neu zeichnen beim horizontalem /vertikalem Verändern

    wnd_class.lpfnWndProc       = WndProc;                          // Callback Funktion

    wnd_class.cbClsExtra        = 0;                                // Keine Extras

    wnd_class.cbWndExtra        = 0;                             
    wnd_class.hInstance         = hInstance;                        // Instanz anpassen

    wnd_class.hIcon             = LoadIcon(NULL, IDI_WINLOGO);      // Windows-Logo setzen

    wnd_class.hCursor           = LoadCursor(NULL, IDC_ARROW);      // Std-Mauszeiger laden


    background.lbStyle          = BS_PATTERN;                                               // Die Bitmap kacheln

    background.lbHatch          = (long)LoadImage(hInstance, L"3D.bmp", IMAGE_BITMAP,       // und als Brush laden

                                                  0, 0, LR_LOADFROMFILE);
    
    wnd_class.hbrBackground     = CreateBrushIndirect(&background); // Die Brush als Hintergrund setzen

    wnd_class.lpszMenuName      = NULL;                             // Kein Menü

    wnd_class.lpszClassName     = L"Fensterklasse";                 // Name der Fensterklasse

    wnd_class.hIconSm           = LoadIcon(NULL, IDI_WINLOGO);      // Fenstericon


    RegisterClassEx(&wnd_class);                                    // Die Klasse registrieren


    // Fenster erstellen

    hwnd = CreateWindow(L"Fensterklasse",           // Klassenname

                        L"Superman",                // Fenstertitel

                        WS_OVERLAPPEDWINDOW,        // Window-Styles

                        CW_USEDEFAULT,              // x-Position

                        CW_USEDEFAULT,              // y-Position

                        CW_USEDEFAULT,              // x-Größe

                        CW_USEDEFAULT,              // y-Größe

                        NULL,                       // Kein übergeordnetes Fenster

                        NULL,                       // Kein Menü

                        hInstance,                  // Instanzhandle

                        NULL);                      // Keine Extra-Daten


    ShowWindow(hwnd, iCmdShow);                     // Fenster anzeigen

    UpdateWindow(hwnd);

    // Fenstermessages verarbeiten

    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    switch(iMsg)
    {
        // Wenn der User das Fenster schließt, Quit Message abschicken

    
        case WM_DESTROY:

            PostQuitMessage(0);

            break;
    }

    return DefWindowProc(hwnd, iMsg, wParam, lParam);   // Std. Messages verarbeiten

}


aber wie kriege ich es jetzt hin dass die komplette Bitmap - egal welche Größe das Fenster hat - immer komplett auf das Fenster angepasst wird. Ich hab gehört es soll irgendwie mit der funktion strtchblt() gehen aber in der msdn hab ich dazu nix gefunden :(

2

31.08.2006, 13:48

Ich hab das so gemacht is aber sicher nicht die beste Lösung:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "main.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND        hwnd;                // Fensterhandle

    MSG            msg;                // Variable für die Fenster-Messages

    WNDCLASSEX    wnd_class;            // Struktur beinhaltet die Fensterattribute

    LOGBRUSH    background;            // Logical Brush, der den Hintergrund beinhaltet


    wnd_class.cbSize            = sizeof(wnd_class);                // Größe der Klasse

    wnd_class.style                = CS_HREDRAW | CS_VREDRAW;            // Neu zeichnen beim horizontalem /vertikalem Verändern

    wnd_class.lpfnWndProc        = WndProc;                            // Callback Funktion

    wnd_class.cbClsExtra        = 0;                                // Keine Extras

    wnd_class.cbWndExtra        = 0;                             
    wnd_class.hInstance            = hInstance;                        // Instanz anpassen

    wnd_class.hIcon                = LoadIcon(NULL, IDI_WINLOGO);        // Windows-Logo setzen

    wnd_class.hCursor            = LoadCursor(NULL, IDC_ARROW);        // Std-Mauszeiger laden


    background.lbStyle            = BS_PATTERN;                                                // Die Bitmap kacheln

    background.lbHatch            = (HBRUSH)GetStockObject(WHITE_BRUSH);
   
    wnd_class.hbrBackground        = CreateBrushIndirect(&background);    // Die Brush als Hintergrund setzen

    wnd_class.lpszMenuName        = NULL;                                // Kein Menü

    wnd_class.lpszClassName        = L"Fensterklasse";                    // Name der Fensterklasse

    wnd_class.hIconSm            = LoadIcon(NULL, IDI_WINLOGO);        // Fenstericon


    RegisterClassEx(&wnd_class);                                    // Die Klasse registrieren


    // Fenster erstellen

    hwnd = CreateWindow(L"Fensterklasse",            // Klassenname

                        L"Superman",                // Fenstertitel

                        WS_OVERLAPPEDWINDOW,        // Window-Styles

                        CW_USEDEFAULT,                // x-Position

                        CW_USEDEFAULT,                // y-Position

                        CW_USEDEFAULT,                // x-Größe

                        CW_USEDEFAULT,                // y-Größe

                        NULL,                        // Kein übergeordnetes Fenster

                        NULL,                        // Kein Menü

                        hInstance,                    // Instanzhandle

                        NULL);                        // Keine Extra-Daten


    ShowWindow(hwnd, iCmdShow);                        // Fenster anzeigen

    UpdateWindow(hwnd);

    // Fenstermessages verarbeiten

    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
} 

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    static int cxClient;
    static int cyClient;
    static int cxSource;
    static int cySource;
    static HBITMAP hBitmap;
    BITMAP bitmap;
    static HINSTANCE hInstance;
    HDC         hdc, hdcMem;
    PAINTSTRUCT ps;

    switch(iMsg)
    {
case WM_CREATE: // Was geschieht gleich beim Start?

        hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
        hBitmap = (HBITMAP)LoadImage(hInstance, TEXT("3D.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        GetObject(hBitmap, sizeof(BITMAP), &bitmap);
        cxSource = bitmap.bmWidth;
        cySource = bitmap.bmHeight;
        return 0;

    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
       
    case WM_PAINT: // Behandlung wenn ungültige Bereiche da sind

        hdc = BeginPaint(hwnd, &ps);

        hdcMem = CreateCompatibleDC(hdc);
        SelectObject(hdcMem, hBitmap);

        StretchBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, cxSource, cySource, SRCCOPY);

        DeleteDC(hdcMem);
        EndPaint(hwnd, &ps);
        return 0;

    case WM_DESTROY: // ENDE

        DeleteObject((HBITMAP)hBitmap);
        PostQuitMessage(0);
        return 0;

    return DefWindowProc(hwnd, iMsg, wParam, lParam);    // Std. Messages verarbeiten

}

3

31.08.2006, 17:33

Zitat von »"Stefan L"«

Ich hab das so gemacht is aber sicher nicht die beste Lösung:

Doch, das ist völlig in Ordnung. Du solltest aber das Zeichnen des Hintergrundes nach WM_ERASEBKGND verlegen, denn genau dafür ist diese Nachricht gedacht. Je nach Fenster-Inhalt kann das Darüberbügeln in WM_PAINT Darstellungs-Probleme verursachen.

4

01.09.2006, 14:20

vielen dank schonmal für den code ;)

aber wenn ich so ein problem hab, wo such ich denn dann am besten nach ner lösung? ich hab per google halt nur dieses vage strtchblt() gefunden und durch die msdn blick ich immernoch net so ganz durch mal abgesehn davon dass man da ziemlich genau wissen muss wonach man sucht ;)

/edit: ähm, warum erkennt er bei mir die DeleteAllBitmaps() nicht? die is doch in der windows.h oder bin ich blöd? O_o

5

01.09.2006, 16:45

Gibt es diese Funktion überhaupt? NOPE :D
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

6

01.09.2006, 22:39

Ne die Funktion gibts ned *gg*.
War ne Funktion, die alle Bitmaps aus nem Menü löschte *gg* hab ich zu löschen vergessen.
Also ich schlag bei solchen Sachen meist entweder in der MSDN oder im Petzold nach.
Der Petzold zahlt sich echt aus wenn man für Windows mit der WinAPI programmiert.

7

02.09.2006, 11:46

also funktionieren tuts schonmal :)

allerdings hab ich das problem dass so komische bunte schlieren in dem bild sind. kann es sein dass ich das in einem bestimmten farbformat speichern muss?

und zweitens: während ich die fenstergröße verändere wird wieder nur ein teil der bitmap angezeigt (so wie es vorher war) und sobald ich den mauszeiger loslasse springt er wieder zurück auf die angepasste bitmap, sodass es dauernd flimmert. kann ich das noch irgendwie umgehen?

koschka

Community-Fossil

Beiträge: 2 862

Wohnort: Dresden

Beruf: Student

  • Private Nachricht senden

8

04.09.2006, 10:00

Du musst die Bitmaps in 24Bit Format abspeichern.

Bei dem vergrößern / verkleinern wird eine Nachricht durch das System geschickt, musst mal suchen ob das eine WM_ ist.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

9

04.09.2006, 11:16

WM_SIZE oder WM_SIZING. (Ist die WinAPI nicht wunderbar logisch?^^)
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

10

04.09.2006, 16:05

1) das mit der bitmap klappt nicht. ich hab 16, 24, 32 bit probiert, überall sind die bunten schlieren drin. also muss der anzeigefehler doch eigentlich in stretchblt() sein oder?

2) ja es heißt WM_SIZE aber da ich die behandlungsroutine von stefan genommen hab steht da folgendes:

C-/C++-Quelltext

1
2
3
4
case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0; 


also setzt er doch beim verschieben den linken bildrand auf den linken fensterrahmen und gleiches beim rechten, das müsste doch stimmen oder muss ichs danach auch nochmal neu zeichnen?

ich glaub ich mach noch ein paar win32 tutorials :D

Werbeanzeige