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

shade1990

Frischling

  • »shade1990« ist der Autor dieses Themas

Beiträge: 31

Beruf: Junior Developer

  • Private Nachricht senden

1

11.10.2016, 10:45

Splash Screen

Hallo an das ganze Spieleprogrammierer Forum/Team.
Ich habe ein kleines Problem. Ich möchte die Ladezeit mit einem Splash Screen überbrücken. Damit der Benutzer nicht mehrmals die Anwendung startet. Ich will nur ein Bild anzeigen und evtl. auch die Version. Mein Quellcode sieht momentan so aus:

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//Erstellt SplashWindow
ATOM SplashRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style      = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = NULL;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = szSplashClass; 
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
    return RegisterClassEx(&wcex);
}

//Bilddatei laden
HBITMAP LoadPicture(HINSTANCE hInstance)
{
    HBITMAP picture = (HBITMAP)::LoadImage(hInstance, L"Software.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    if (picture == NULL) 
    {
        ::MessageBox(NULL, __T("Image not Found"), __T("Error"), MB_OK);
    }

    return picture;
}

//Bitmap anzeigen
void ShowBitMap(HWND hwnd, HINSTANCE hInstance)
{
    TEST = hInstance;

    int nuXPos = 0; 
    int nuYPos = 0; 
    int width = 0;
        int height = 0;
    BITMAP bm;

    //Bitmap laden, bei Fehler Nachrricht anzeigen
    hbmpSplash = LoadPicture(hInstance);

    //Bestimmt groesse der Bilddatei
    GetObject(hbmpSplash, sizeof(bm),&bm);
    SIZE size = {bm.bmHeight, bm.bmWidth};
    width =  bm.bmWidth;
    height = bm.bmHeight;

    //Positionierung der Anzeige
    POINT ptZero = { 0 };
    HMONITOR hmonPrimary = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
    MONITORINFO monitorinfo = { 0 };
    monitorinfo.cbSize = sizeof(monitorinfo);
    GetMonitorInfo(hmonPrimary, &monitorinfo);

    const RECT & rcWork = monitorinfo.rcWork;

    nuXPos = rcWork.left + (rcWork.right - rcWork.left) / 2;
    nuYPos = rcWork.top + (rcWork.bottom - rcWork.top) / 2;

    nuXPos = nuXPos - (175/2);
    nuYPos = nuYPos - (170/2);

        HDC hdcScreen = GetDC(NULL);
    HDC hdcMem = CreateCompatibleDC(hdcScreen);
    HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmpSplash);

    //Fensterposition bestimmen
    POINT position = {nuXPos, nuYPos};
    
    BLENDFUNCTION blend = { 0 };
        blend.BlendOp = AC_SRC_OVER;
        blend.SourceConstantAlpha = 255;
        blend.AlphaFormat = AC_SRC_ALPHA;

    //Bild ausgeben
    if ( !UpdateLayeredWindow(splashOwner, hdcScreen, &position, &size, hdcMem, NULL, RGB(0,0,0), &blend, ULW_ALPHA) )
    { 
        //int LastError = GetLastError();
        //TCHAR Buffer[100];
        //wsprintf(Buffer, L"Errorcode: %d",LastError);
        //::MessageBox(NULL, Buffer, __T("Error"), MB_OK);
    }

    SelectObject(hdcMem, hbmpOld);
    DeleteDC(hdcMem);
    ReleaseDC(NULL, hdcScreen);
}

//Slpash Fenster erzeugen
HWND CreateSplashWindow(HINSTANCE hInstance, int nCmdShow)
{
    //Splash Fenster registrieren
    SplashRegisterClass(hInstance);

    //Fenster anzeigen
    splashOwner = CreateWindowEx(WS_EX_LAYERED, szSplashClass, NULL, WS_POPUP, 0, 0, 100, 100, NULL, NULL, hInstance, NULL);
    if (!splashOwner)
    {
        //int LastError = GetLastError();
        //TCHAR Buffer[100];
        //wsprintf(Buffer, L"Errorcode: %d",LastError);
        //::MessageBox(NULL, Buffer, __T("Error"), MB_OK);
    }

    //die Bitmap Datei suchen, laden und anzeigen
    ShowBitMap(splashOwner, hInstance);

    if (!SetLayeredWindowAttributes(splashOwner, RGB(0,0,0), 255, LWA_COLORKEY | LWA_ALPHA) )
    {
        //int LastError = GetLastError();
        //TCHAR Buffer[100];
        //wsprintf(Buffer, L"Errorcode: %d",LastError);
        //::MessageBox(NULL, Buffer, __T("Error"), MB_OK);
    }

    //Das Splash Fenster zurueckgeben
    return splashOwner;
}

//Loescht Bitmap
void DeleteSplashWindow()
{
    DeleteObject(hbmpSplash);
    ReleaseDC(splashOwner,0);
}

Die Bildausgabe mit UpdateLayeredWindow funktioniert nicht, bzw. ich sehe nichts. Keine Ahnung warum. ?( Ich sehe den Fehler einfach nicht.
Danke schon mal im Voraus für die Hilfe.

shade1990

Frischling

  • »shade1990« ist der Autor dieses Themas

Beiträge: 31

Beruf: Junior Developer

  • Private Nachricht senden

2

14.10.2016, 14:34

Habe den Fehler gefunden! :D

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

3

14.10.2016, 14:44

Dann teile die Lösung doch mit Leuten, die eventuell später auf dasselbe Problem stoßen und hier landen...
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

shade1990

Frischling

  • »shade1990« ist der Autor dieses Themas

Beiträge: 31

Beruf: Junior Developer

  • Private Nachricht senden

4

14.10.2016, 15:18

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
// SplashWindow.cpp : Definiert den Einstiegspunkt für die Anwendung.
//

#include "stdafx.h"
#include "SplashWindow.hpp"

using namespace Gdiplus;

#pragma comment (lib,"Gdiplus.lib")

//Globale Variablen:
//Splash Fenster Besitzer
HWND splashOwner;
//Splash Fenster Instanz speichern
HINSTANCE splashInstance;
// Klassenname des Hauptfensters
TCHAR szSplashClass[] = L"SplashWindow";            
//Übernimmt GDI-plus malen
LRESULT CALLBACK    WndProcSplash(HWND, UINT, WPARAM, LPARAM);

//Erstellt SplashWindow
ATOM SplashRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProcSplash;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = NULL;
    wcex.hCursor        = NULL;
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = szSplashClass; 
    wcex.hIconSm        = NULL;
    
    return RegisterClassEx(&wcex);
}

//Bilddatei laden
void LoadPicture(HDC hdcpic)
{
    Graphics graphics(hdcpic);
    //                   a, r,   g,  b
    Pen      pen(Color(255, 0, 183, 235));
    //                        a, r,  g,  b
    SolidBrush  brushVersion(Color(255, 0, 183, 235));
    //Font bestimmen und laden
    FontFamily  fontFamily(L"Times New Roman");
    //Schriftgroesse einstellen
    Font        fontVersion(&fontFamily, 24, FontStyleRegular, UnitPixel);
    //Position             x,    y, orientiert sich am Bild bzw. Splash Fenster
    PointF      pointF(10.0f, 165.0f);

    //Versions Informationen
    const WCHAR *version = L"Splash Version 1.0";

    //Bild laden
    //auf gross und klein Schreibung muss nicht geachtet werden, nur auf richtige Dateiendung
    Image image(L"software.jpg");
    //Wird das Bild nciht geladen, wird eine Bild mit GDIplus erstellt
    Gdiplus::Status e = image.GetLastStatus();
    if(e != Gdiplus::Ok)
    {
        SolidBrush  brush(Color(255, 0, 0, 255));
        Font        font(&fontFamily, 55, FontStyleRegular, UnitPixel);
        SolidBrush  brushBlue(Color(255, 153, 124, 118));
        SolidBrush  brushWhite(Color(255, 255, 255, 255));
        //Zeichne Ellipse aussen braun 
        graphics.FillEllipse(&brushBlue,40,40,110,110);
        //Zeichne Ellipse aussen weiss
        graphics.FillEllipse(&brushWhite,50,50,90,90);
        //Zeichne Ellipse innen braun
        graphics.FillEllipse(&brushBlue,70,70,50,50);
        //Zeichne Ellipse innen weiss
        graphics.FillEllipse(&brushWhite,80,80,30,30);
        PointF      pointWin(40.0f, 50.0f);
        graphics.DrawString(L"Test", -1, &font, pointWin, &brush);
        PointF      pointIpro(50.0f, 85.0f);
        graphics.DrawString(L"Test2", -1, &font, pointIpro, &brush);
    }
    else
    {
        //Bild wird oben links ausgerichtet am Splash Fenster
        graphics.DrawImage(&image, 0, 0);
    }

    //Ausgabe der Versionsnummer
    graphics.DrawString(version, -1, &fontVersion, pointF, &brushVersion);
}

//Bitmap und Version anzeigen
void ShowBitMap(HWND hwnd, HINSTANCE hInstance)
{
    //Erstellen der X und Y Koordinate
    int nuXPos = 0; 
    int nuYPos = 0; 

    //Positionierung der Anzeige
    POINT ptZero = { 0 };
    HMONITOR hmonPrimary = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
    MONITORINFO monitorinfo = { 0 };
    monitorinfo.cbSize = sizeof(monitorinfo);
    GetMonitorInfo(hmonPrimary, &monitorinfo);

    const RECT & rcWork = monitorinfo.rcWork;

    nuXPos = rcWork.left + (rcWork.right - rcWork.left) / 2;
    nuYPos = rcWork.top + (rcWork.bottom - rcWork.top) / 2;

    nuXPos = nuXPos - (175/2);
    nuYPos = nuYPos - (170/2);

    HDC hdcScreen = GetDC(NULL);
    HDC hdcMem = CreateCompatibleDC(hdcScreen);
    
    //Fensterposition bestimmen
    POINT position = {nuXPos, nuYPos};

    //Festlegen der groesse
    SIZE size = { 200, 200 };

    //setzen des Alphakanals
    BLENDFUNCTION blend = { 0 };
    blend.BlendOp = AC_SRC_OVER;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;
     
    //Bild ausgeben
    UpdateLayeredWindow(splashOwner, hdcScreen, &position, &size, hdcMem, NULL, RGB(0,0,0), &blend, ULW_ALPHA);
    /*
    if ( !UpdateLayeredWindow(splashOwner, hdcScreen, &position, &size, hdcMem, NULL, RGB(0,0,0), &blend, ULW_ALPHA) )
    { 
        //int LastError = GetLastError();
        //TCHAR Buffer[100];
        //wsprintf(Buffer, L"Errorcode: %d",LastError);
        //::MessageBox(NULL, Buffer, __T("Error"), MB_OK);
    }
    */

    //Ressourcen freigeben
    ::DeleteDC(hdcMem);
    ::ReleaseDC(NULL, hdcScreen);
}

//Slpash Fenster erzeugen
void CreateSplashWindow(HINSTANCE hInstance, int nCmdShow)
{
    //Splash Fenster Instanz speichern
    splashInstance = hInstance;

    //GDI plus Variablen
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR           gdiplusToken;
    
    // Initialsiere GDI+.
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    //Splash Fenster registrieren
    SplashRegisterClass(splashInstance);

    //Fenster anzeigen
    splashOwner = CreateWindowEx(WS_EX_LAYERED, szSplashClass, L"Splash", WS_POPUP, 0, 0, 100, 100, NULL, NULL, hInstance, NULL);
    /*
    if (!splashOwner)
    {
        //int LastError = GetLastError();
        //TCHAR Buffer[100];
        //wsprintf(Buffer, L"Errorcode: %d",LastError);
        //::MessageBox(NULL, Buffer, __T("Error"), MB_OK);
    }
    */

    //Splash Fenster ausgeben
    ShowWindow(splashOwner, nCmdShow);

    //Bilddatei suchen, laden und anzeigen
    ShowBitMap(splashOwner, hInstance);

    SetLayeredWindowAttributes(splashOwner, RGB(0,0,0), 255, LWA_COLORKEY | LWA_ALPHA);
    /*
    if (!SetLayeredWindowAttributes(splashOwner, RGB(0,0,0), 255, LWA_COLORKEY | LWA_ALPHA) )
    {
        //int LastError = GetLastError();
        //TCHAR Buffer[100];
        //wsprintf(Buffer, L"Errorcode: %d",LastError);
        //::MessageBox(NULL, Buffer, __T("Error"), MB_OK);
    }
    */
    //Splash Fenster ueberarbeiten
    UpdateWindow(splashOwner);

    //Gdiplus schließen
    GdiplusShutdown(gdiplusToken);
}

//Übernimmt GDI-plus malen
LRESULT CALLBACK WndProcSplash(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            //aufruf zum Bild malen
            LoadPicture(hdc);
            EndPaint(hWnd, &ps);
        break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

//Loescht Splash Fenster
void DeleteSplashWindow()
{   
    //Splash Fenster löschen
    ReleaseDC(splashOwner, NULL);
    ShowWindow(splashOwner, 0);
}


Ich glaube zwar nicht, dass irgendjemand so blöde ist wie ich :crazy: und die "ShowWindow(splashOwner, nCmdShow);" vergisst, aber hier mal der ganze Quellcode! :thumbsup:

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »shade1990« (14.10.2016, 15:26)


shade1990

Frischling

  • »shade1990« ist der Autor dieses Themas

Beiträge: 31

Beruf: Junior Developer

  • Private Nachricht senden

5

17.10.2016, 11:16

Ich habe da mal noch eine Frage. Momentan ist es so, wenn ich mit GDI+ etwas ausgeben will, benutze ich die WndProc/WndProcSplash.
Ist es Möglich, ohne WndProc und ohne WM_PAINT direkt mit GDI+ etwas auszugeben? :hmm:
Verkürzt:
In der SplashRegisterClass soll dann die Zeile wegfallen:

C-/C++-Quelltext

1
wcex.lpfnWndProc = WndProcSplash;
oder durch default ersetzt werden.
Und es sollte auch das hier wegfallen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
RESULT CALLBACK WndProcSplash(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            //aufruf zum Bild malen
            LoadPicture(hdc);
            EndPaint(hWnd, &ps);
        break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

Tobiking

1x Rätselkönig

  • Private Nachricht senden

6

17.10.2016, 12:17


Ist es Möglich, ohne WndProc und ohne WM_PAINT direkt mit GDI+ etwas auszugeben? :hmm:

Soweit ich weiß kommst du nicht ohne WndProc wenn du ein Fenster erzeugst (unabhängig von GDI+). Lässt du es weg und die Nachrichtenverarbeitung läuft, wirst du dort vermutlich eine Zugriffsverletzung bekommen, weil dort dann ein invalider Wert steht. Läuft die Nachrichtenverarbeitung nicht, wird Windows dir sagen das die Anwendung nicht mehr reagiert und dir vorschlagen sie zu beenden.

shade1990

Frischling

  • »shade1990« ist der Autor dieses Themas

Beiträge: 31

Beruf: Junior Developer

  • Private Nachricht senden

7

17.10.2016, 16:30

Man kann ja auch DefWindowProc verwenden und dann hatte ich die Idee direkt mit GDI+ etwas auszugeben.

Ich habe das mal umgestellt. In der RegisterClass steht jetzt DefWindowProc, dann erstelle ich das Fenster,danach wird LoadPicture aufgerufen und er läuft auch durch, danach kommt dann ShowWindow und ich sehe ein graues Fenster, eigentlich sollten da Ellipsen sein. Später wird dann UpdatelayerdWindow aufgerufen und es passiert nichts!
Nach UpdateWindow(splashOwner); wird ja dann die default aufgerufen und die kennt ja die LoadPicture nicht.

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
//Erstellt SplashWindow
ATOM SplashWindow::SplashRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX splw;

    splw.cbSize = sizeof(WNDCLASSEX);
    splw.style      = CS_HREDRAW | CS_VREDRAW;
    splw.lpfnWndProc    = DefWindowProc; //WndProcSplash;
    splw.cbClsExtra     = 0;
    splw.cbWndExtra     = 0;
    splw.hInstance      = hInstance;
    splw.hIcon      = NULL;
    splw.hCursor        = NULL;
    splw.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    splw.lpszMenuName   = L"";
    splw.lpszClassName  = szSplashClass; 
    splw.hIconSm        = NULL;

    splregcla = true;

    return RegisterClassEx(&splw);
}


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
//Fenster anzeigen
splashOwner = CreateWindowEx(WS_EX_LAYERED, szSplashClass, L"Splash", WS_POPUP, nuXPos, nuYPos, widthEx, heightEx, NULL, NULL, splashInstance, NULL);
if (!splashOwner)
{
   ::MessageBox(NULL, __T("Splash Window Creation failed"), __T("Error"), MB_OK);
}
    
PAINTSTRUCT ps;
HDC hdc;

hdc = BeginPaint(splashOwner, &ps);
//aufruf zum Bild malen
LoadPicture(hdc); 
EndPaint(splashOwner, &ps);

//Splash Fenster ausgeben
ShowWindow(splashOwner, SW_SHOW);

//setzt die UpdateLayerdWindow Attribute
SetLayeredWindowAttributes(splashOwner, RGB(0,0,0), 255, LWA_COLORKEY | LWA_ALPHA);
    
//Bild ausgeben, das Bild wird ueber die WndProcSplash schon bereitgestellt und mit diesen Befehl auf dem Fenster gezeichnet
if ( !UpdateLayeredWindow(splashOwner, NULL, &position, &size, hdc, NULL, RGB(0,0,0), &blend, ULW_ALPHA) )
{ 
   //LastError();
   }

//Splash Fenster ueberarbeiten
UpdateWindow(splashOwner);

Werbeanzeige