Inputbox (oder allg. Dialoge ohne Resourcen)



  • naja, ich wusel so ein bisschen in Opengl rum und wollte aber vom user noch eine zahl abfragen, bevor das programm richtig startet, also mit windows und VC++, OpenGL und wenig ahnung 😉

    aber ein NIMM-Spiel habe icch schon hinbekommen *g*
    - 21 streichhölzer am anfang, man nimmt immer 1-3, dann comp, wer das letzt zieht hat verloren *bg* -



  • Ich verscheibe den Thread ins WinAPI Forum.



  • Da musst du dir wohl oder übel einen eigenen Dialog basteln.



  • ...oder WebFritzi arbeiten lassen. 😉 Ich habe jetzt die ganze Nacht durchgearbeitet, um diesen dummen Dialog zu basteln (ohne Resource). Dabei ist folgende cpp-Datei herausgekommen ([edit]überarbeitete Version[/edit]):

    Die zur cpp-Datei gehörige Header-Datei (*.h)
    ----------------------------------------------
    
    //---------------------------------------------------------------------------
    #ifndef DynDialogsH
    #define DynDialogsH
    //---------------------------------------------------------------------------
    #include <windows.h>
    //---------------------------------------------------------------------------
    
    // Input-Box-Childs
    #define  ID_INPUT     200
    #define  ID_INFOTEXT  201
    
    // Control Classes
    #define  BUTTON_CLASS       0x0080
    #define  EDIT_CLASS         0x0081
    #define  STATIC_CLASS       0x0082
    #define  LISTBOX_CLASS      0x0083
    #define  SCROLLBAR_CLASS    0x0084
    #define  COMBOBOX_CLASS     0x0085
    
    // Definitions of icon representations in ShowMessage()
    #define  SM_NONE       0
    #define  SM_WARNING    1
    #define  SM_INFO       2
    #define  SM_ERROR      3
    //---------------------------------------------------------------------------
    
    LPWORD          DWORD_ALIGN(LPWORD);
    LPWORD          NON_DWORD_ALIGN(LPWORD);
    LPWORD          InitDialog(LPVOID, LPCTSTR, DWORD, WORD, LPCTSTR, WORD, short, short, short, short);
    LPWORD          CreateDlgControl(LPWORD, WORD, WORD, LPCTSTR, DWORD, short, short, short, short);
    int             InputBox(HWND, LPCTSTR, LPCTSTR, LPTSTR, INT);
    VOID            ShowMessage(HWND, LPCTSTR, LPCTSTR, WORD);
    BOOL  CALLBACK  InputBoxDlgProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
    //---------------------------------------------------------------------------
    #endif
    
    Die cpp-Datei
    --------------
    
    //---------------------------------------------------------------------------
    #include "DynDialogs.h" 
    //---------------------------------------------------------------------------
    
    LPWORD DWORD_ALIGN(LPWORD lpIn)
    {
       ULONG ul = (ULONG)lpIn;
    
       ul += 3;
       ul >>= 2;
       ul <<= 2;
    
       return (LPWORD)ul;
    }
    //---------------------------------------------------------------------------
    
    LPWORD NON_DWORD_ALIGN(LPWORD lpIn)
    {
       return (DWORD_ALIGN(lpIn - 1) + 1);
    }
    //---------------------------------------------------------------------------
    
    LPWORD InitDialog(LPVOID lpv, LPCTSTR title, DWORD style, WORD ctrlno, LPCTSTR fontname,
                      WORD fontsize, short x, short y, short cx, short cy)
    {
        LPWORD        lpw;
        LPWSTR        lpwsz;
        int           nchar, wcharlength;
        LPDLGTEMPLATE lpdt = (LPDLGTEMPLATE)lpv;
    
        lpdt->style = style;
        lpdt->dwExtendedStyle = 0;
        lpdt->cdit = ctrlno;
        lpdt->x  = x;  lpdt->y  = y;
        lpdt->cx = cx; lpdt->cy = cy;
    
        lpw = (LPWORD)(lpdt + 1);
    
        // No menu
        *lpw = 0;
        lpw++;
    
        // Predefined dialog box class (by default)
        *lpw = 0;
        lpw++;
    
        // The title
        lpwsz = (LPWSTR)lpw;
        wcharlength = MultiByteToWideChar(CP_ACP, 0, title, -1, lpwsz, 0);
        nchar = MultiByteToWideChar(CP_ACP, 0, title, -1, lpwsz, wcharlength);
        lpw += nchar;
    
        // The font used in dialog
        if(style & DS_SETFONT)
        {
           *lpw = 8;
           lpw++;
           lpwsz = (LPWSTR)lpw;
           wcharlength = MultiByteToWideChar(CP_ACP, 0, fontname, -1, lpwsz, 0);
           nchar = MultiByteToWideChar(CP_ACP, 0, fontname, -1, lpwsz, wcharlength);
           lpw += nchar;
        }
    
        return lpw;
    }
    //---------------------------------------------------------------------------
    
    LPWORD CreateDlgControl(LPWORD lpw, WORD ctrlclass, WORD id, LPCTSTR caption,
                          DWORD style, short x, short y, short cx, short cy)
    {
        LPDLGITEMTEMPLATE lpdit;
        LPWSTR            lpwsz;
        int               nchar, wcharlength;
    
        lpw = DWORD_ALIGN(lpw);
        lpdit = (LPDLGITEMTEMPLATE)lpw;
        lpdit->style = style;
        lpdit->dwExtendedStyle = 0;
        lpdit->x  = x ; lpdit->y  = y;
        lpdit->cx = cx; lpdit->cy = cy;
        lpdit->id = id;
    
        // class
        lpw = (LPWORD)(lpdit + 1);
        *lpw = 0xFFFF;
        lpw++;
        *lpw = ctrlclass;
        lpw++;
    
        // title
        lpwsz = (LPWSTR)lpw;
        wcharlength = MultiByteToWideChar(CP_ACP, 0, caption, -1, lpwsz, 0);
        nchar = MultiByteToWideChar(CP_ACP, 0, caption, -1, lpwsz, wcharlength);
        lpw += nchar;
    
        // no creation data
        lpw = NON_DWORD_ALIGN(lpw);
        *lpw = 0;
        lpw++;
    
        return lpw;
    }
    //---------------------------------------------------------------------------
    
    int InputBox(HWND hwnd, LPCTSTR prompt, LPCTSTR title, LPTSTR buffer, INT buflength)
    {
        HGLOBAL  hgbl;
        LPWORD   lpw;
        LRESULT  ret;
        DWORD    style;
    
        hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
        if(!hgbl) return 0;
        LPVOID lpv = GlobalLock(hgbl);
    
        // Prepare the dialog box
        style = DS_SETFONT | DS_CENTER | DS_3DLOOK | WS_POPUP | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | WS_VISIBLE;
        lpw = InitDialog(lpv, title, style, 4, "MS Sans Serif", 8, 0, 0, 319, 47);
    
        // OK-Button
        style = WS_CHILD | WS_VISIBLE | WS_TABSTOP |BS_DEFPUSHBUTTON;
        lpw = CreateDlgControl(lpw, BUTTON_CLASS, IDOK, "OK", style, 264, 7, 48, 15);
    
        // Cancel-Button
        style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON;
        lpw = CreateDlgControl(lpw, BUTTON_CLASS, IDCANCEL, "Abbrechen", style, 264, 26, 48, 15);
    
        // Text to prompt
        style = WS_CHILD | WS_VISIBLE | SS_LEFT;
        lpw = CreateDlgControl(lpw, STATIC_CLASS, ID_INFOTEXT, prompt, style, 10, 9, 129, 16);
    
        // Edit-Control
        style = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP;
        lpw = CreateDlgControl(lpw, EDIT_CLASS, ID_INPUT, "", style, 10, 26, 249, 13);
    
        GlobalUnlock(hgbl);
        int data[2] = {(int)buffer, buflength};
        ret = DialogBoxIndirectParam(NULL, (LPDLGTEMPLATE)hgbl, hwnd,
                                     (DLGPROC)InputBoxDlgProc, (int)data);
        GlobalFree(hgbl);
        return (ret > 0) ? ret : 0;
    }
    //---------------------------------------------------------------------------
    
    BOOL CALLBACK InputBoxDlgProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
    {
       static char* buf;
       static int   buflength;
       static HFONT hFont;
    
       switch(uiMsg)
       {
          case WM_INITDIALOG:
          {
             int* data = (int*)lParam;
             buf = (char*)data[0];
             buflength = data[1];
             HWND hEdit = GetDlgItem(hwnd, ID_INPUT);
             SetFocus(hEdit);
             break;
          }
    
          case WM_SETFONT:
             hFont = (HFONT)wParam;
             break;
    
          case WM_CLOSE:
             EndDialog(hwnd, IDCANCEL);
             DeleteObject(hFont);
             break;
    
          case WM_COMMAND:
          {
             switch(LOWORD(wParam))
             {
                case IDOK:
                {
                   HWND hEdit = GetDlgItem(hwnd, ID_INPUT);
                   GetWindowText(hEdit, buf, buflength);
                   EndDialog(hwnd, IDOK);
                   DeleteObject(hFont);
                   break;
                }
    
                case IDCANCEL:
                {
                   EndDialog(hwnd, IDCANCEL);
                   break;
                }
             }
          }
       }
       return FALSE;
    }
    //---------------------------------------------------------------------------
    
    VOID ShowMessage(HWND hwnd, LPCTSTR lpszMsg, LPCTSTR lpszTitle, WORD wIcon)
    {
       UINT uType = 0;
       if(wIcon == SM_WARNING)
          uType = MB_ICONWARNING;
       else if(wIcon == SM_INFO)
          uType = MB_ICONINFORMATION;
       else if(wIcon == SM_ERROR)
          uType = MB_ICONERROR;
    
       MessageBox(hwnd, lpszMsg, lpszTitle, uType);
    }
    //---------------------------------------------------------------------------
    

    Dann kannst du eine solche InputBox wie folgt aufrufen:

    char buffer[256];
    
    int ret = InputBox(hwnd, "Eingabe in diesem Feld:", "Titel", buffer, 256);
    if(ret == IDOK)
       MessageBox(hwnd, buffer, "Die Eingabe war:", MB_OK | MB_ICONINFORMATION);
    else if(ret == IDCANCEL)
       MessageBox(hwnd, "Es wurde \"Abbrechen\" gewählt", "INFO", MB_OK | MB_ICONINFORMATION);
    else if(ret == 0)
       MessageBox(hwnd, "Ein Fehler ist aufgetreten", "INFO", MB_OK | MB_ICONERROR);
    

    Ich habe jetzt rund 48 Stunden dafür gebraucht. Dabei war Knobeln an der Tagesordnung, denn die MS-Dokumentation zu DialogBoxIndirect() ist sehr schlecht und fehlerhaft in mehreren Punkten. Im Netz ist auch nicht das Wahre zu finden. Aber jetzt steht das ganze hoffentlich (ohne Fehler), und man kann nicht nur InputBoxes damit erstellen, sondern Dialoge jeglicher Art. Dazu schaue man sich die Funktion InputBox() an. Diese nutzt wiederum die Funktionen InitDialog() und CreateDlgControl(), mit denen man seinen Dialog erstellen kann wie auch in einem Resourcen-Script. Viel Spaß damit.

    [ Dieser Beitrag wurde am 22.02.2003 um 21:30 Uhr von WebFritzi editiert. ]



  • öhm ... WebFritzi, bin hier mal als Trittbrettfahrer. Son Ding hab ich schon öfter gebraucht, bin blos bislang nicht dazu gekommen das selber zu basteln. Hab deinen Code zwar noch nicht probiert, aber sieht gut aus. Denke, ich werd da einen "Standard-Include" bei mir draus machen.
    Vielleicht kann ich mich ja mal mit irgendwas revangieren.



  • @WebFritz: Warum hast du das mit diesem dummen DLGITEMTEMPLATE gemacht und nicht mit CreateWindow? 😕



  • @frage!
    Weil ich das eben mit nem Dialog machen wollte. Hast du noch nie das Gefühl gehabt, eine Herausforderung annehmen zu müssen? 😉

    @dange!
    Bidde!

    [ Dieser Beitrag wurde am 11.12.2002 um 00:23 Uhr von WebFritzi editiert. ]



  • Für den FAQ-Leser: Alles, was jetzt noch kommt, ist unwichtig!

    [ Dieser Beitrag wurde am 11.12.2002 um 00:24 Uhr von WebFritzi editiert. ]



  • mach doch SendMessage mit WM_SETFONT



  • hi,

    ich hätte nicht gedacht, dass es so schwer ist eine inputbox zu machen,
    das ist ja wahnsinn, bin ich der erste der sowas braucht(e)??

    ich schaffs nicht, die datei einzubinden, der meckert immer irgendwo rum,
    ich habe eine inputbox.h erstellt, in der steht das:

    int InputBox(HINSTANCE hInst, HWND hwnd, LPCTSTR prompt, LPCTSTR title, LPTSTR buffer, INT buflength);
    

    und die datei die hier gepostet ist habe ich inputbox.cpp genannt.
    dann habe ich das hier versucht:

    int i = InputBox(hInstance, hWnd, "Eingabe in diesem Feld:", "Titel", sDummy, 256);
    if(i==IDOK)
    { MessageBox(NULL, sDummy, "Text", MB_OK); }
    

    bei den ersten beiden parametern habe ich mein problem,
    NULL kann ich nicht bei beiden nehmen, das weiß ich jetzt auch schon,
    aber wenn ich
    hInstanc2 als HINSTANCE
    und
    hWn2 als HWND
    deklariere, dann kommt diese meldung:

    error LNK2001: unresolved external symbol "int __cdecl InputBox(struct HINSTANCE__ *,struct HWND__ *,char const *,char const *,char *,int)" (?InputBox@@YAHPAUHINSTANCE__@@PAUHWND__@@PBD2PADH@Z)
    Debug/Nimm3D.exe : fatal error LNK1120: 1 unresolved externals
    Error executing link.exe.
    

    ist bestimmt wieder nur n minifehler von mir, aber ich hab das mit hwnd und hinstance... noch nicht so raus! 😞

    Danke für die Mühe,

    Cu, Ronny



  • Du solltest den Code von WebFritzi auch noch als .cpp datei speichern und dazulinken. 🙂

    @WebFritzi:
    Ist der Code so in Ordnung? Ich schiebs dann nämlich mal in die FAQ, da sowas ja öfter gebraucht wird.



  • Original erstellt von Netspider:
    **
    und die datei die hier gepostet ist habe ich inputbox.cpp genannt.
    **

    habe ich ja, zumindest gespeichert, ich dachte es reicht wenn ich die InputBox.h include, aber ok!
    muss ich die ersten 2 parameter eigentlich ändern oder geht das so wie es im beispiel von webfritzi geschrieben ist?



  • @cd9000
    JETZT ist der Code hoffentlich in Ordnung, und ich wäre dankbar dafür, wenn du das in die FAQ stellen würdest. Dann kann ich mir wenigstens immer wieder die Früchte meiner Anstrengung anschauen. 😉

    @Netspider
    Den ersten Parameter habe ich in der neuen Fassung herausgenommen. Der war eh überflüssig, weil man in DialogBoxIndirectParam() auch NULL im ersten Parameter stehen haben kann, wenn man die DLGTEMPLATE nicht gerade aus einer Resource geladen hat. Du solltest jetzt keine Probleme mehr damit haben. Tipp einfach das Beispiel in meinem langen Beitrag ab.



  • WebFritzi: Fein, danke! 🙂



  • irgendwie bin ich nicht in der lage, das zu starten: *grübel*

    error LNK2001: unresolved external symbol "int __cdecl InputBox(struct HWND__ *,char const *,char const *,char *,int)" (?InputBox@@YAHPAUHWND__@@PBD1PADH@Z)
    Debug/Nimm3D.exe : fatal error LNK1120: 1 unresolved externals
    Error executing link.exe.
    

    ich habe #include "InputBox.h" gemacht, die neue version von deiner cpp-datei in die InputBox.cpp geschrieben und die InputBox.h mit deinem text geschrieben.
    dann habe ich die funktion so aufgerufen:

    int i = InputBox(hWnd, "Eingabe in diesem Feld:", "Titel", sDummy, 256);
    if(i==IDOK)
    { MessageBox(NULL, sDummy, "Text", MB_OK); }
    

    was ist denn daran falsch, muss ich ein frisches "hWnd" benutzen, das hier ist das von meinem fenster, das erstellt wurde.
    - ich kenn mich mit win-cpp eben nicht so aus -
    Danke für eure hilfe, wenn mir noch jemand dabei helfen kann, den error auszuradieren, dann bin ich richtig glücklich!

    Cu, Ronny



  • Du musst natürlich die cpp-Datei zu deinem Projekt hinzufügen (Im VC++: Projekt->Dem Projekt hinzufügen...).


Anmelden zum Antworten