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

Gotbread

Alter Hase

  • »Gotbread« ist der Autor dieses Themas

Beiträge: 421

Beruf: Student (Etechnik) + Hiwi

  • Private Nachricht senden

1

17.03.2010, 00:35

InputBox innerhalb WndProc

Hallo

ich möchte eine "InputBox" erstellen, ein kleines fenster, mit eingabezeile
und ok-button.

meine bisherige version funktioniert an sich auch, mit einer ausnahme:
wenn sie innerhalb der WndProc des hauptfensters aufgerufen wird,
lässt sie sich nicht bewegen, die knöpfe reagieren nicht.

das teil hängt dann total.

wenn das eintritt, kann ich sie aber immernoch über das drücken der
entertaste schließen, weil das inputcontrol entsprechend ge-subclasst
ist.

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
struct InputBoxStruct
{
    HWND input, button;
    std::string str;
    volatile bool close;
    WNDPROC oldproc;
};
LRESULT CALLBACK InputBoxProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    InputBoxStruct *str = reinterpret_cast<InputBoxStruct *>(GetWindowLongPtrA(hWnd, 0));

    switch (Msg)
    {
    case WM_CREATE:
        {
            CREATESTRUCT *cs = reinterpret_cast<CREATESTRUCT *>(lParam);
            SetWindowLongPtrA(hWnd, 0, reinterpret_cast<long>(cs->lpCreateParams));
        }
        break;
    case WM_COMMAND:
        {
            if (str && LOWORD(wParam) == 42 && ((HWND)lParam) == str->button)
            {
                unsigned size = GetWindowTextLength(str->input);
                str->str.resize(size + 1);
                GetWindowText(str->input, &str->str[0], size + 1);
                str->close = true;
            }
        }
        break;
    case WM_CLOSE:
        {
            if (str)
            {
                str->str = "";
                str->close = true;
            }
        }
        break;
    }

    return DefWindowProc(hWnd, Msg, wParam, lParam);
}
LRESULT CALLBACK InputBoxEditProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    InputBoxStruct *str = reinterpret_cast<InputBoxStruct *>(GetWindowLongPtrA(hWnd, GWLP_USERDATA));

    switch (Msg)
    {
    case WM_KEYDOWN:
        {
            if (str && wParam == VK_RETURN)
            {
                unsigned size = GetWindowTextLength(str->input);
                str->str.resize(size + 1);
                GetWindowText(str->input, &str->str[0], size + 1);
                str->close = true;
            }
        }
        break;
    }

    if (str && str->oldproc)
        return CallWindowProcA(str->oldproc, hWnd, Msg, wParam, lParam);

    return DefSubclassProc(hWnd, Msg, wParam, lParam);
}
std::string InputBox(const std::string &title, bool password = true)
{
    WNDCLASS wc = {0};
    wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    wc.hInstance = GetModuleHandle(0);
    wc.lpfnWndProc = InputBoxProc;
    wc.lpszClassName = "InputBox";
    wc.cbWndExtra = sizeof(InputBoxStruct *);
    
    RegisterClass(&wc);

    InputBoxStruct str;
    str.button = 0;
    str.input = 0;
    str.close = false;
    str.str = "";
    str.oldproc = 0;

    HWND mainwnd = CreateWindowExA(0, wc.lpszClassName, title.c_str(), WS_CAPTION | WS_SYSMENU,
        CW_USEDEFAULT, CW_USEDEFAULT, 300, 65, 0, 0, GetModuleHandle(0), &str);

    HWND input = CreateWindowExA(0, "EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | (password ? ES_PASSWORD : 0),
        5, 5, 250, 25, mainwnd, 0, GetModuleHandle(0), 0);
    
    HWND button = CreateWindowExA(0, "BUTTON", "OK", WS_VISIBLE | WS_CHILD | WS_BORDER, 260, 5, 30, 25,
        mainwnd, (HMENU)42, GetModuleHandle(0), 0);

    SetWindowLongPtrA(input, GWLP_USERDATA, reinterpret_cast<long>(&str));
    long proc = GetWindowLongPtrA(input, GWLP_WNDPROC);
    str.oldproc = reinterpret_cast<WNDPROC>(proc);
    SetWindowLongPtrA(input, GWLP_WNDPROC, (LONG)InputBoxEditProc);

    ShowWindow(mainwnd, SW_SHOWNORMAL);
    SetFocus(input);

    str.button = button;
    str.input = input;

    MSG msg;
    while (GetMessage(&msg, 0, 0, 0) && !str.close)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    SetWindowLongPtrA(input, GWLP_USERDATA, 0);
    SetWindowLongPtrA(input, GWLP_WNDPROC, (LONG)str.oldproc);

    DestroyWindow(mainwnd);
    UnregisterClass(wc.lpszClassName, GetModuleHandle(0));

    return str.str;
}


weder WM_COMMAND noch WM_CLOSE kommen an.
wenn ich einen breakpoint nach dem ersten createwindow setze,
und dann direkt weitermache, funktioniert es komischerweise
normal.

vielleicht weil dadurch a) das hauptfenster minimiert wird, oder b)
das fenster n bissel zeit bekommt (wofür auch immer).

wenn ich es ohne hauptfenster, am anfang von winmain
aufrufe, geht es auch normal
.
Mfg Goti
www.gotbread.bplaced.net
viele tolle spiele kostenlos, viele hardware-basteleien :)

"Es ist nicht undicht, es läuft über" - Homer Simpson

Gotbread

Alter Hase

  • »Gotbread« ist der Autor dieses Themas

Beiträge: 421

Beruf: Student (Etechnik) + Hiwi

  • Private Nachricht senden

2

18.03.2010, 16:40

kann einer von euch die funktionsfähigkeit der inputbox den bestätigen?
Mfg Goti
www.gotbread.bplaced.net
viele tolle spiele kostenlos, viele hardware-basteleien :)

"Es ist nicht undicht, es läuft über" - Homer Simpson

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

3

18.03.2010, 17:57

An welcher Stelle in der WndProc vom Hauptfenster erzeugst du denn die Inputbox, damit das Fehlverhalten auftritt?

Bei folgendem funktioniert es bei mir:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch ( msg )
    {
    case WM_LBUTTONDOWN:
        MessageBox( NULL, InputBox( "foobar" ).c_str(), "Info", MB_OK | MB_ICONINFORMATION );
        break;

    case WM_CLOSE:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc( hWnd, msg, wParam, lParam );
    }

    return 0;
}

Gotbread

Alter Hase

  • »Gotbread« ist der Autor dieses Themas

Beiträge: 421

Beruf: Student (Etechnik) + Hiwi

  • Private Nachricht senden

4

18.03.2010, 18:06

hier:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
// ...

else if (p->Message == WM_TIMER)
{
    if (!pw_command.empty())
    {
        KillTimer(w->GetHandle(), (UINT_PTR)1); // damit die nachricht nicht nochmal gesendet wird

    
        EnableWindow(w->GetHandle(), 0);
        std::string pw_str = InputBox("Passwort eingeben!");
        EnableWindow(w->GetHandle(), 1);
Mfg Goti
www.gotbread.bplaced.net
viele tolle spiele kostenlos, viele hardware-basteleien :)

"Es ist nicht undicht, es läuft über" - Homer Simpson

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

5

18.03.2010, 18:15

Folgendes funktioniert Problemlos (zumindest bei mir unter Win7):

C-/C++-Quelltext

1
2
3
4
5
6
case WM_TIMER:
    KillTimer( hWnd, 0 );
    EnableWindow( hWnd, 0 );
    MessageBox( NULL, InputBox( hWnd, "foobar" ).c_str(), "Info", MB_OK | MB_ICONINFORMATION );
    EnableWindow( hWnd, 1 );
    break;

Gotbread

Alter Hase

  • »Gotbread« ist der Autor dieses Themas

Beiträge: 421

Beruf: Student (Etechnik) + Hiwi

  • Private Nachricht senden

6

20.03.2010, 17:11

wenn ich kurz den fokus wechsle und dann wieder auf die input box kann
ich sie wieder bewegen.
Mfg Goti
www.gotbread.bplaced.net
viele tolle spiele kostenlos, viele hardware-basteleien :)

"Es ist nicht undicht, es läuft über" - Homer Simpson

Werbeanzeige