int far pascal zDialogBoxIndirect( HANDLE pp1, HANDLE pp2, HWND pp3, FARPROC pp4 ) { int r; FARPROC fp ; SaveRegs(); fp = pp4 ; if (fp) { pp4 = (FARPROC)HookAdd( (void far *)DlgMesgProc, (void far *)fp ); } /* ** Log IN Parameters (No Create/Destroy Checking Yet!) */ LogIn( (LPSTR)"APICALL:DialogBoxIndirect HANDLE+HANDLE+HWND+FARPROC+", pp1, pp2, pp3, pp4 ); /* ** Call the API! */ RestoreRegs(); GrovelDS(); r = DialogBoxIndirect(pp1,pp2,pp3,pp4); UnGrovelDS(); SaveRegs(); /* ** Log Return Code & OUT Parameters (No Create/Destroy Checking Yet!) */ LogOut( (LPSTR)"APIRET:DialogBoxIndirect int+++++", r, (short)0, (short)0, (short)0, (short)0 ); RestoreRegs(); return( r ); }
void deviceconfig_open(HWND hwnd, device_t *device) { device_config_t *config = device->config; uint16_t *data_block = malloc(16384); uint16_t *data; DLGTEMPLATE *dlg = (DLGTEMPLATE *)data_block; DLGITEMTEMPLATE *item; int y = 10; int id = IDC_CONFIG_BASE; memset(data_block, 0, 4096); dlg->style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU; dlg->x = 10; dlg->y = 10; dlg->cx = 220; dlg->cy = 70; data = (uint16_t *)(dlg + 1); *data++ = 0; /*no menu*/ *data++ = 0; /*predefined dialog box class*/ data += MultiByteToWideChar(CP_ACP, 0, "Device Configuration", -1, data, 50); *data++ = 8; /*Point*/ data += MultiByteToWideChar(CP_ACP, 0, "MS Sans Serif", -1, data, 50); #ifndef __MINGW64__ if (((unsigned long)data) & 2) #else if (((unsigned long long)data) & 2) #endif data++; while (config->type != -1) { switch (config->type) { case CONFIG_BINARY: item = (DLGITEMTEMPLATE *)data; item->x = 10; item->y = y; item->id = id++; item->cx = 80; item->cy = 15; item->style = WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX; data = (uint16_t *)(item + 1); *data++ = 0xFFFF; *data++ = 0x0080; // button class data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); *data++ = 0; // no creation data y += 20; break; case CONFIG_SELECTION: case CONFIG_MIDI: /*Combo box*/ item = (DLGITEMTEMPLATE *)data; item->x = 70; item->y = y; item->id = id++; item->cx = 140; item->cy = 150; item->style = WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_VSCROLL; data = (uint16_t *)(item + 1); *data++ = 0xFFFF; *data++ = 0x0085; // combo box class data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); *data++ = 0; // no creation data #ifndef __MINGW64__ if (((unsigned long)data) & 2) #else if (((unsigned long long)data) & 2) #endif data++; /*Static text*/ item = (DLGITEMTEMPLATE *)data; item->x = 10; item->y = y; item->id = id++; item->cx = 60; item->cy = 15; item->style = WS_CHILD | WS_VISIBLE; data = (uint16_t *)(item + 1); *data++ = 0xFFFF; *data++ = 0x0082; // static class data += MultiByteToWideChar(CP_ACP, 0, config->description, -1, data, 256); *data++ = 0; // no creation data #ifndef __MINGW64__ if (((unsigned long)data) & 2) #else if (((unsigned long long)data) & 2) #endif data++; y += 20; break; } #ifndef __MINGW64__ if (((unsigned long)data) & 2) #else if (((unsigned long long)data) & 2) #endif data++; config++; } dlg->cdit = (id - IDC_CONFIG_BASE) + 2; // DEFPUSHBUTTON "OK",IDOK,64,232,50,14, WS_TABSTOP // PUSHBUTTON "Cancel",IDCANCEL,128,232,50,14, WS_TABSTOP item = (DLGITEMTEMPLATE *)data; item->x = 20; item->y = y; item->cx = 50; item->cy = 14; item->id = IDOK; // OK button identifier item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; data = (uint16_t *)(item + 1); *data++ = 0xFFFF; *data++ = 0x0080; // button class data += MultiByteToWideChar(CP_ACP, 0, "OK", -1, data, 50); *data++ = 0; // no creation data #ifndef __MINGW64__ if (((unsigned long)data) & 2) #else if (((unsigned long long)data) & 2) #endif data++; item = (DLGITEMTEMPLATE *)data; item->x = 80; item->y = y; item->cx = 50; item->cy = 14; item->id = IDCANCEL; // OK button identifier item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; data = (uint16_t *)(item + 1); *data++ = 0xFFFF; *data++ = 0x0080; // button class data += MultiByteToWideChar(CP_ACP, 0, "Cancel", -1, data, 50); *data++ = 0; // no creation data dlg->cy = y + 20; config_device = device; DialogBoxIndirect(hinstance, dlg, hwnd, deviceconfig_dlgproc); free(data_block); }
int DebugWinlogonInterface::WlxDialogBoxIndirect(HANDLE hInst, LPCDLGTEMPLATE hDialogTemplate, HWND hwndOwner, DLGPROC dlgprc) { return (int) DialogBoxIndirect((HINSTANCE) hInst, hDialogTemplate, hwndOwner, dlgprc); }
int WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) { WIN_DialogData *dialog; int i, x, y; UINT_PTR which; const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons; HFONT DialogFont; SIZE Size; RECT TextSize; wchar_t* wmessage; TEXTMETRIC TM; const int ButtonWidth = 88; const int ButtonHeight = 26; const int TextMargin = 16; const int ButtonMargin = 12; /* Jan 25th, 2013 - [email protected] * * * I've tried to make this more reasonable, but I've run in to a lot * of nonsense. * * The original issue is the code was written in pixels and not * dialog units (DLUs). All DialogBox functions use DLUs, which * vary based on the selected font (yay). * * According to MSDN, the most reliable way to convert is via * MapDialogUnits, which requires an HWND, which we don't have * at time of template creation. * * We do however have: * The system font (DLU width 8 for me) * The font we select for the dialog (DLU width 6 for me) * * Based on experimentation, *neither* of these return the value * actually used. Stepping in to MapDialogUnits(), the conversion * is fairly clear, and uses 7 for me. * * As a result, some of this is hacky to ensure the sizing is * somewhat correct. * * Honestly, a long term solution is to use CreateWindow, not CreateDialog. * * * In order to get text dimensions we need to have a DC with the desired font. * I'm assuming a dialog box in SDL is rare enough we can to the create. */ HDC FontDC = CreateCompatibleDC(0); { /* Create a duplicate of the font used in system message boxes. */ LOGFONT lf; NONCLIENTMETRICS NCM; NCM.cbSize = sizeof(NCM); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0); lf = NCM.lfMessageFont; DialogFont = CreateFontIndirect(&lf); } /* Select the font in to our DC */ SelectObject(FontDC, DialogFont); { /* Get the metrics to try and figure our DLU conversion. */ GetTextMetrics(FontDC, &TM); s_BaseUnitsX = TM.tmAveCharWidth + 1; s_BaseUnitsY = TM.tmHeight; } /* Measure the *pixel* size of the string. */ wmessage = WIN_UTF8ToString(messageboxdata->message); SDL_zero(TextSize); Size.cx = DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT); /* Add some padding for hangs, etc. */ TextSize.right += 2; TextSize.bottom += 2; /* Done with the DC, and the string */ DeleteDC(FontDC); SDL_free(wmessage); /* Increase the size of the dialog by some border spacing around the text. */ Size.cx = TextSize.right - TextSize.left; Size.cy = TextSize.bottom - TextSize.top; Size.cx += TextMargin * 2; Size.cy += TextMargin * 2; /* Ensure the size is wide enough for all of the buttons. */ if (Size.cx < messageboxdata->numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin) Size.cx = messageboxdata->numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin; /* Add vertical space for the buttons and border. */ Size.cy += ButtonHeight + TextMargin; dialog = CreateDialogData(Size.cx, Size.cy, messageboxdata->title); if (!dialog) { return -1; } if (!AddDialogStatic(dialog, TextMargin, TextMargin, TextSize.right - TextSize.left, TextSize.bottom - TextSize.top, messageboxdata->message)) { FreeDialogData(dialog); return -1; } /* Align the buttons to the right/bottom. */ x = Size.cx - (ButtonWidth + ButtonMargin) * messageboxdata->numbuttons; y = Size.cy - ButtonHeight - ButtonMargin; for (i = messageboxdata->numbuttons - 1; i >= 0; --i) { SDL_bool isDefault; if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) { isDefault = SDL_TRUE; } else { isDefault = SDL_FALSE; } if (!AddDialogButton(dialog, x, y, ButtonWidth, ButtonHeight, buttons[i].text, i, isDefault)) { FreeDialogData(dialog); return -1; } x += ButtonWidth + ButtonMargin; } /* FIXME: If we have a parent window, get the Instance and HWND for them */ which = DialogBoxIndirect(NULL, (DLGTEMPLATE*)dialog->lpDialog, NULL, (DLGPROC)MessageBoxDialogProc); *buttonid = buttons[which].buttonid; FreeDialogData(dialog); return 0; }
/* * The purpose of this function is to layout and display the pub/sub options * dialog based on a variable number of input options. The input option * mask dictates which options are enabled by default, while the output mask is * used to indicate which options were selected by the user (from the * available options specified by in. Mask determines which options are available. */ void showOptionsDlg(HWND parent, char **optionLabels, int numOptions, Options *in, Options *out, Options *mask) { HDC dc = GetDC(parent); //need to create font used by dialog and select into context //so that we can compute text string sizes HFONT font = CreateFont(8, 0, 0, 0, FW_NORMAL, false, false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "MS Shell Dlg"); SelectObject(dc, (HGDIOBJ) font); SIZE sz; optsIn = in; optsOut = out; optsMask = mask; numOpts = numOptions; char desc[1024]; int plistExists = 0; //This is the number of individual items that will be created within the dialog //7 represents 3 static stings + 4 push buttons //* 3 represents the 3 items per option (option name + 2 checkboxes) int numItems = 7 + numOptions * 3; int textHeight = 0; int textWidth = 0; //Row start y coordinate begins after accounting for the border height int rowStart = BORDER; //loop to find the widest/tallest option label for (int i = 0; i < numOptions; i++) { GetTextExtentPoint32(dc, optionLabels[i], strlen(optionLabels[i]), &sz); if (sz.cy > textHeight) { textHeight = sz.cy; } if (sz.cx > textWidth) { textWidth = sz.cx; } } //comput the vertical height of the push buttons int buttonHeight = textHeight * 2; //compute the width of the buttons based on the width of the longest button label //the size in the following allows for 2 spaces on either side of the label GetTextExtentPoint32(dc, "Subscribe Only", 18, &sz); int buttonWidth = sz.cx; //compute the width and height of the dialog box based on the //sums of the component dimensions and spacing short height = 2 * BORDER + (numOptions + 1) * textHeight + (numOptions) * TEXT_SPACING + TEXT_TO_BUTTON_SPACING + BUTTON_SPACING + buttonHeight * 2; short width = 2 * BORDER + textWidth + 2 * CB_SIZE + 2 * CB_SPACE; //compute width required to accomodate the buttons short buttonReqWidth = BORDER * 2 + 2 * buttonWidth + BUTTON_SPACING; //recompute width if buttons are wider than option labels if (width < buttonReqWidth) { width = buttonReqWidth; } //compute x offset to the pub checkboxes int cbStart = width - BORDER - 2 * CB_SIZE - 2 * CB_SPACE; //build the dialog template into a Buffer Buffer dlgTemplate; DLGTEMPLATE temp, *pTemp; temp.style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_CENTER | DS_MODALFRAME | WS_CAPTION | DS_SETFONT; temp.dwExtendedStyle = 0; temp.cdit = numItems; temp.x = 0; temp.y = 0; temp.cx = width; temp.cy = height; dlgTemplate.write(&temp, sizeof(temp)); dlgTemplate.writeShort(0); //no menu dlgTemplate.writeShort(0); //predefined dialog class desc[0] = '\0'; plistExists = GetDlgItemText(parent, IDC_PROJECT_LIST, desc, sizeof(desc)); //if(GetDlgItemText(parent, IDC_PROJECT_LIST, desc, sizeof(desc)) ) { //GetDlgItem returns #TChar or NULL if (strcmp(desc, "<New project>") == 0 || !plistExists) { //should be for snapshots too... dlgTemplate.writeWide("Set Permissions"); //unicode dialog title } else { dlgTemplate.writeWide("Project Join Options"); //unicode dialog title } #if DEBUG msg(PLUGIN_NAME": PROJECT LIST is %s , strcmp is: %d \n", desc,strcmp(desc,"<New project>")); #endif dlgTemplate.writeShort(0x0800); //font size in network byte order dlgTemplate.writeWide("MS Shell Dlg"); //unicode font name padBuffer(dlgTemplate); DLGITEMTEMPLATE item, text; //common values for all static text elements //Start with the three static column headers text.style = WS_CHILD | WS_VISIBLE | SS_LEFT; text.dwExtendedStyle = 0; text.x = BORDER; text.y = rowStart; text.cx = textWidth; text.cy = textHeight; text.id = 0xFFFF; dlgTemplate.write(&text, sizeof(text)); dlgTemplate.write(STATIC_CLASS, sizeof(STATIC_CLASS)); //item class dlgTemplate.writeWide("Options"); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); //center the Pub label over the pub checkbox location GetTextExtentPoint32(dc, "Pub", 3, &sz); text.x = cbStart + (CB_SIZE - sz.cx) / 2; text.cx = sz.cx; dlgTemplate.write(&text, sizeof(text)); dlgTemplate.write(STATIC_CLASS, sizeof(STATIC_CLASS)); //item class dlgTemplate.writeWide("Pub"); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); //center the Sub label over the sub checkbox location GetTextExtentPoint32(dc, "Sub", 3, &sz); text.x = cbStart + CB_SIZE + CB_SPACE + (CB_SIZE - sz.cx) / 2; text.cx = sz.cx; dlgTemplate.write(&text, sizeof(text)); dlgTemplate.write(STATIC_CLASS, sizeof(STATIC_CLASS)); //item class dlgTemplate.writeWide("Sub"); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); rowStart += textHeight; item.style = WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | WS_TABSTOP; item.dwExtendedStyle = 0; item.cx = CB_SIZE; item.cy = CB_SIZE; //print all of the option labels and their checkboxes int bit = 1; for (int i = 0; i < numOptions; i++) { rowStart += TEXT_SPACING; text.x = BORDER; text.y = rowStart; text.cx = textWidth; dlgTemplate.write(&text, sizeof(text)); dlgTemplate.write(STATIC_CLASS, sizeof(STATIC_CLASS)); //item class dlgTemplate.writeWide(optionLabels[i]); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); //test option bits to see if the publish bit is set if (optsMask->pub & bit) { item.style &= ~WS_DISABLED; } else { item.style |= WS_DISABLED; } item.x = cbStart; item.y = rowStart; item.id = COLLAB_CB_BASE + i * 2; dlgTemplate.write(&item, sizeof(item)); dlgTemplate.write(BUTTON_CLASS, sizeof(BUTTON_CLASS)); //item class dlgTemplate.writeWide(""); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); //test option bits to see if the subscribe bit is set if (optsMask->sub & bit) { item.style &= ~WS_DISABLED; } else { item.style |= WS_DISABLED; } item.x = cbStart + CB_SIZE + CB_SPACE; item.id = COLLAB_CB_BASE + i * 2 + 1; dlgTemplate.write(&item, sizeof(item)); dlgTemplate.write(BUTTON_CLASS, sizeof(BUTTON_CLASS)); //item class dlgTemplate.writeWide(""); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); rowStart += textHeight; bit <<= 1; } rowStart += TEXT_TO_BUTTON_SPACING; //layout the 4 pushbuttons item.style = WS_CHILD | WS_VISIBLE | BS_CENTER | BS_PUSHBUTTON | WS_TABSTOP; item.x = (width - 2 * buttonWidth - BUTTON_SPACING) / 2; item.y = rowStart; item.cx = buttonWidth; item.cy = buttonHeight; item.id = COLLAB_SUB_ALL; dlgTemplate.write(&item, sizeof(item)); dlgTemplate.write(BUTTON_CLASS, sizeof(BUTTON_CLASS)); //item class dlgTemplate.writeWide("Subscribe All"); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); item.x += buttonWidth + BUTTON_SPACING; item.id = COLLAB_SUB_ONLY; dlgTemplate.write(&item, sizeof(item)); dlgTemplate.write(BUTTON_CLASS, sizeof(BUTTON_CLASS)); //item class dlgTemplate.writeWide("Subscribe Only"); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); rowStart += buttonHeight + BUTTON_SPACING; //must align each item to dword item.style = WS_CHILD | WS_VISIBLE | BS_CENTER | BS_DEFPUSHBUTTON | WS_TABSTOP; item.x = (width - 2 * buttonWidth - BUTTON_SPACING) / 2; item.y = rowStart; item.id = IDOK; dlgTemplate.write(&item, sizeof(item)); dlgTemplate.write(BUTTON_CLASS, sizeof(BUTTON_CLASS)); //item class dlgTemplate.writeWide("OK"); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); //must align each item to dword item.style = WS_CHILD | WS_VISIBLE | BS_CENTER | BS_PUSHBUTTON | WS_TABSTOP; item.x += buttonWidth + BUTTON_SPACING; item.id = IDCANCEL; dlgTemplate.write(&item, sizeof(item)); dlgTemplate.write(BUTTON_CLASS, sizeof(BUTTON_CLASS)); //item class dlgTemplate.writeWide("Cancel"); //item text unicode dlgTemplate.writeShort(0); //class data padBuffer(dlgTemplate); // hexDump(dlgTemplate.get_buf(), dlgTemplate.size()); //need to point this to "global memory" ?? HGLOBAL hgbl = GlobalAlloc(GMEM_ZEROINIT, dlgTemplate.size()); DLGTEMPLATE *lpdt = (DLGTEMPLATE*)GlobalLock(hgbl); memcpy(lpdt, dlgTemplate.get_buf(), dlgTemplate.size()); GlobalUnlock(hgbl); int res = DialogBoxIndirect(hModule, (LPDLGTEMPLATE)hgbl, parent, OptionsDlgProc); if (res == 1) { //read checkboxes for options } else if (res == -1) { DWORD err = GetLastError(); msg(PLUGIN_NAME": Options dialog error %d, 0x%x\n", err, err); } GlobalFree(hgbl); ReleaseDC(parent, dc); }
BOOL Win32PopupDialog::ShowMessageBox(HWND hwnd) { BOOL fSuccess = FALSE; HDC hdc = GetDC(hwnd); if (hdc) { NONCLIENTMETRICSW ncm = { sizeof(ncm) }; if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0)) { DialogTemplate tmp; std::wstring ws; int controlCount = 2; // at minimum, static label and OK button if(this->showCancelButton) controlCount++; if(this->showInputText) controlCount++; int labelHeight = 14; int width = 300; int height = 90; int margin = 10; int buttonWidth = 50; int buttonHeight = 14; int inputHeight = 14; if(! this->showInputText) { height -= (inputHeight + margin); } // Write out the extended dialog template header tmp.Write<WORD>(1); // dialog version tmp.Write<WORD>(0xFFFF); // extended dialog template tmp.Write<DWORD>(0); // help ID tmp.Write<DWORD>(0); // extended style tmp.Write<DWORD>(WS_CAPTION | DS_FIXEDSYS | DS_SETFONT | DS_MODALFRAME); // DS_FIXEDSYS removes the close decoration tmp.Write<WORD>(controlCount); // number of controls tmp.Write<WORD>(32); // X tmp.Write<WORD>(32); // Y tmp.Write<WORD>(width); // width tmp.Write<WORD>(height); // height tmp.WriteString(L""); // no menu tmp.WriteString(L""); // default dialog class //tmp.WriteString(pszTitle); // title tmp.WriteString(ws.assign(title.begin(), title.end()).c_str()); // title // Next comes the font description. // See text for discussion of fancy formula. if (ncm.lfMessageFont.lfHeight < 0) { ncm.lfMessageFont.lfHeight = -MulDiv(ncm.lfMessageFont.lfHeight, 72, GetDeviceCaps(hdc, LOGPIXELSY)); } tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfHeight); // point tmp.Write<WORD>((WORD)ncm.lfMessageFont.lfWeight); // weight tmp.Write<BYTE>(ncm.lfMessageFont.lfItalic); // Italic tmp.Write<BYTE>(ncm.lfMessageFont.lfCharSet); // CharSet tmp.WriteString(ncm.lfMessageFont.lfFaceName); // First control - static label tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE); // style tmp.Write<WORD>(margin); // x tmp.Write<WORD>(margin); // y tmp.Write<WORD>(width - (2 * margin)); // width tmp.Write<WORD>(labelHeight); // height tmp.Write<DWORD>(-1); // control ID tmp.Write<DWORD>(0x0082FFFF); // static tmp.WriteString(ws.assign(message.begin(), message.end()).c_str()); // text tmp.Write<WORD>(0); // no extra data // Second control - the OK button. tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON); // style tmp.Write<WORD>(width - margin - buttonWidth); // x tmp.Write<WORD>(height - margin - buttonHeight); // y tmp.Write<WORD>(buttonWidth); // width tmp.Write<WORD>(buttonHeight); // height tmp.Write<DWORD>(IDOK); // control ID tmp.Write<DWORD>(0x0080FFFF); // button class atom tmp.WriteString(L"OK"); // text tmp.Write<WORD>(0); // no extra data if(this->showCancelButton) { // The Cancel button tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON); // style tmp.Write<WORD>(width - 2 * margin - 2 * buttonWidth); // x tmp.Write<WORD>(height - margin - buttonHeight); // y tmp.Write<WORD>(buttonWidth); // width tmp.Write<WORD>(buttonHeight); // height tmp.Write<DWORD>(IDCANCEL); // control ID tmp.Write<DWORD>(0x0080FFFF); // button class atom tmp.WriteString(L"Cancel"); // text tmp.Write<WORD>(0); // no extra data } if(this->showInputText) { // The input field tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE); // style tmp.Write<WORD>(margin); // x tmp.Write<WORD>(margin + labelHeight + margin); // y tmp.Write<WORD>(width - (2 * margin)); // width tmp.Write<WORD>(inputHeight); // height tmp.Write<DWORD>(ID_INPUT_FIELD); // control ID tmp.Write<DWORD>(0x0081FFFF); // edit class atom tmp.WriteString(ws.assign(inputText.begin(), inputText.end()).c_str()); // text tmp.Write<WORD>(0); // no extra data } // Template is ready - go display it. fSuccess = DialogBoxIndirect(GetModuleHandle(NULL), tmp.Template(), hwnd, &Win32PopupDialog::Callback) >= 0; } ReleaseDC(NULL, hdc); // fixed 11 May } return fSuccess; }
//----------------------------------------------------------------------------------------------------------------------------------------- // Create the Dialog Box to get input from the user //----------------------------------------------------------------------------------------------------------------------------------------- LRESULT DisplayMiniDumpDialog(HINSTANCE hinst, HWND hwndOwner) { HGLOBAL hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024); if (!hgbl) return -1; //----------------------------------------------------------------- // Define the dialog box //----------------------------------------------------------------- LPDLGTEMPLATE lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); lpdt->style = WS_POPUP | WS_BORDER | DS_MODALFRAME | WS_CAPTION; lpdt->cdit = 3; // Number of controls lpdt->x = 100; lpdt->y = 100; lpdt->cx = 300; lpdt->cy = 90; LPWORD lpw = (LPWORD)(lpdt + 1); *lpw++ = 0; // No menu *lpw++ = 0; // Predefined dialog box class (by default) LPWSTR lpwsz = (LPWSTR)lpw; S32 nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "MiniDump Crash Report", -1, lpwsz, 50); lpw += nchar; //----------------------------------------------------------------- // Define a static text message //----------------------------------------------------------------- lpw = lpwAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary LPDLGITEMTEMPLATE lpdit = (LPDLGITEMTEMPLATE)lpw; lpdit->x = 10; lpdit->y = 10; lpdit->cx = 290; lpdit->cy = 10; lpdit->id = ID_TEXT; // Text identifier lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // Static class LPSTR msg = "The program has crashed. Please describe what was happening:"; for (lpwsz = (LPWSTR)lpw; *lpwsz++ = (WCHAR)*msg++;); lpw = (LPWORD)lpwsz; *lpw++ = 0; // No creation data //----------------------------------------------------------------- // Define a DONE button //----------------------------------------------------------------- lpw = lpwAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE)lpw; lpdit->x = 265; lpdit->y = 75; lpdit->cx = 25; lpdit->cy = 12; lpdit->id = ID_DONE; // OK button identifier lpdit->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP;// | BS_DEFPUSHBUTTON; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // Button class lpwsz = (LPWSTR)lpw; nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "Done", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // No creation data //----------------------------------------------------------------- // Define a text entry message //----------------------------------------------------------------- lpw = lpwAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE)lpw; lpdit->x = 10; lpdit->y = 22; lpdit->cx = 280; lpdit->cy = 50; lpdit->id = ID_USERTEXT; // Text identifier lpdit->style = ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0081; // Text edit class *lpw++ = 0; // No creation data GlobalUnlock(hgbl); LRESULT ret = DialogBoxIndirect( hinst, (LPDLGTEMPLATE)hgbl, hwndOwner, (DLGPROC)MiniDumpDialogProc); GlobalFree(hgbl); return ret; }
BOOL Win32PopupDialog::ShowMessageBox(HWND hwnd) { BOOL fSuccess = FALSE; HDC hdc = GetDC(hwnd); if (hdc) { NONCLIENTMETRICSW nonClientMetrics = { sizeof(NONCLIENTMETRICSW) }; if (SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, 0, &nonClientMetrics, 0)) { DialogTemplate tmp; std::wstring wideTitle(::UTF8ToWide(title)); std::wstring wideInputText; if (this->showInputText) wideInputText.assign(::UTF8ToWide(inputText)); int controlCount = 2; // at minimum, static label and OK button if (this->showCancelButton) controlCount++; if (this->showInputText) controlCount++; int messageLines = 0; int newlines = CountMatches(message, "\n"); int tabs = CountMatches(message, "\t"); int spaces = CountMatches(message, " "); if (newlines == 0 && tabs == 0 && spaces == 0) { std::string tempMessage(message); if (tempMessage.length() != 0) { int insertAt = 60; int count = 0; std::string::iterator it = tempMessage.begin(); for (; it < tempMessage.end(); it++) { count++; if (count == 60) { count = 0; message.insert(insertAt, "\n"); insertAt += 60; } } } } std::wstring wideMessage(::UTF8ToWide(message)); messageLines = message.length() / 60; messageLines += ((int) ceil((double)tabs / 14)); messageLines += newlines; if (tabs == 0 || newlines == 0) messageLines++; int labelHeight = 14; int width = 200; int margin = 10; int buttonWidth = 50; int buttonHeight = 14; int inputHeight = 14; int messageHeight = (messageLines * 12) + (messageLines * margin); int height = messageHeight + 56; if (!this->showInputText) { height -= (inputHeight + margin); } // Write out the extended dialog template header tmp.Write<WORD>(1); // dialog version tmp.Write<WORD>(0xFFFF); // extended dialog template tmp.Write<DWORD>(0); // help ID tmp.Write<DWORD>(0); // extended style tmp.Write<DWORD>(WS_CAPTION | WS_BORDER | DS_ABSALIGN | DS_SETFONT); tmp.Write<WORD>(controlCount); // number of controls tmp.Write<WORD>(32); // X tmp.Write<WORD>(32); // Y tmp.Write<WORD>(width); // width tmp.Write<WORD>(height); // height tmp.WriteString(L""); // no menu tmp.WriteString(L""); // default dialog class //tmp.WriteString(pszTitle); // title tmp.WriteString(wideTitle.c_str()); // title // Next comes the font description. // See text for discussion of fancy formula. if (nonClientMetrics.lfMessageFont.lfHeight < 0) { int dpi = GetDeviceCaps(hdc, LOGPIXELSY); nonClientMetrics.lfMessageFont.lfHeight = -MulDiv(nonClientMetrics.lfMessageFont.lfHeight, 72, dpi); } tmp.Write<WORD>((WORD)nonClientMetrics.lfMessageFont.lfHeight); // point tmp.Write<WORD>((WORD)nonClientMetrics.lfMessageFont.lfWeight); // weight tmp.Write<BYTE>(nonClientMetrics.lfMessageFont.lfItalic); // Italic tmp.Write<BYTE>(nonClientMetrics.lfMessageFont.lfCharSet); // CharSet tmp.WriteString(nonClientMetrics.lfMessageFont.lfFaceName); // First control - static label tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE | SS_LEFT); // style tmp.Write<WORD>(margin); // x tmp.Write<WORD>(margin); // y tmp.Write<WORD>(width - (2 * margin)); // width //tmp.Write<WORD>(labelHeight); // height tmp.Write<WORD>(messageHeight); // height tmp.Write<DWORD>(-1); // control ID tmp.Write<DWORD>(0x0082FFFF); // static //tmp.Write<DWORD>(SS_LEFT); tmp.WriteString(wideMessage.c_str()); // text tmp.Write<WORD>(0); // no extra data // Second control - the OK button. tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON); // style tmp.Write<WORD>(width - margin - buttonWidth); // x tmp.Write<WORD>(height - margin - buttonHeight); // y tmp.Write<WORD>(buttonWidth); // width tmp.Write<WORD>(buttonHeight); // height tmp.Write<DWORD>(IDCANCEL); // control ID tmp.Write<DWORD>(0x0080FFFF); // button class atom tmp.WriteString(L"Cancel"); // text tmp.Write<WORD>(0); // no extra data if (this->showCancelButton) { // The Cancel button tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON); // style tmp.Write<WORD>(width - 2 * margin - 2 * buttonWidth); // x tmp.Write<WORD>(height - margin - buttonHeight); // y tmp.Write<WORD>(buttonWidth); // width tmp.Write<WORD>(buttonHeight); // height tmp.Write<DWORD>(IDOK); // control ID tmp.Write<DWORD>(0x0080FFFF); // button class atom tmp.WriteString(L"OK"); // text tmp.Write<WORD>(0); // no extra data } if (this->showInputText) { // The input field tmp.AlignToDword(); tmp.Write<DWORD>(0); // help id tmp.Write<DWORD>(0); // window extended style tmp.Write<DWORD>(ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD | WS_VISIBLE); // style tmp.Write<WORD>(margin); // x tmp.Write<WORD>(margin + labelHeight + margin); // y tmp.Write<WORD>(width - (2 * margin)); // width tmp.Write<WORD>(inputHeight); // height tmp.Write<DWORD>(ID_INPUT_FIELD); // control ID tmp.Write<DWORD>(0x0081FFFF); // edit class atom tmp.WriteString(wideInputText.c_str()); // text tmp.Write<WORD>(0); // no extra data } // Template is ready - go display it. fSuccess = DialogBoxIndirect( GetModuleHandle(NULL), tmp.Template(), hwnd, &Win32PopupDialog::Callback) >= 0; } ReleaseDC(NULL, hdc); // fixed 11 May } return fSuccess; }
LRESULT DisplayMessage(wchar_t* title, int title_len, wchar_t* message, int message_len, wchar_t* button_label[], int button_len[], int num_buttons) { DLGTEMPLATE* dlg_template; DLGITEMTEMPLATE* item_template; WORD* cursor; // 16 bits words pointer LRESULT ret_code; void* buf; int i; int next_x; int button_width = 80; // Width of a button int button_gap = 6; // Width of the space separating two buttons int left_margin = 10; // Left dialog margin int right_margin = 10; // Right dialog margin int top_margin = 10; int bottom_margin = 10; int static_height = 40; // Height of the space where static text is displayed int static_to_buttons_margin = num_buttons > 0 ? 5 : 0; int button_height = num_buttons > 0 ? 15 : 0; int num_gaps = num_buttons ? num_buttons -1 : 0; int static_width = num_buttons ? num_buttons * button_width + button_gap * num_gaps : 80; int buf_len; int font_len = wcslen(FONT_NAME); // Compute length of work buffer and allocate it buf_len = sizeof(DLGTEMPLATE) + 4 + title_len + 1 + font_len + 1 + message_len + 1 + sizeof(DLGITEMTEMPLATE) + 4 + 2 + num_buttons * sizeof(DLGITEMTEMPLATE) + + 100; // Allow for into account possible alignment padding as well as extra fields (class atoms, user data) for (i=0; i<num_buttons; i++) buf_len += button_len[i] + 1; buf = malloc(buf_len); dlg_template = (DLGTEMPLATE*) buf; // Dialog header dlg_template->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_SETFONT; dlg_template->dwExtendedStyle = 0; dlg_template->cdit = 1 + num_buttons; // Number of controls dlg_template->x = 0; // In Dialog Box Units dlg_template->y = 0; dlg_template->cx = left_margin + static_width + right_margin; dlg_template->cy = top_margin + static_height + static_to_buttons_margin + button_height + bottom_margin; cursor = (WORD*)(dlg_template + 1); // Point past DLGTEMPLATE structure *cursor++ = 0; // Menu *cursor++ = 0; // Default Dialog class // Copy title, add NUL and shift cursor wmemcpy(cursor, title, title_len); cursor += title_len; *cursor++ = 0; // Type point and font name (as DS_FONT was specified) *cursor++ = FONT_SIZE; wmemcpy(cursor, FONT_NAME, font_len); cursor += font_len; *cursor++ = 0; // Item templates need to be DWORD aligned ALIGN4(cursor); // Static control item_template = (DLGITEMTEMPLATE*) cursor; item_template->style = WS_CHILD | WS_VISIBLE | SS_CENTER; item_template->dwExtendedStyle = 0; item_template->x = left_margin; item_template->y = top_margin; item_template->cx = static_width; item_template->cy = static_height; item_template->id = -1; // Move past DLGITEMTEMPLATE structure cursor = (WORD*)(item_template + 1); // Static class *cursor++ = 0xFFFF; *cursor++ = 0x0082; // Title wmemcpy(cursor, message, message_len); cursor += message_len; *cursor++ = 0; // Empty user data block *cursor++ = 0; next_x = left_margin; // Additional controls for (i=0; i<num_buttons; i++) { ALIGN4(cursor); item_template = (DLGITEMTEMPLATE*) cursor; item_template->style = WS_CHILD | WS_VISIBLE; item_template->dwExtendedStyle = 0; item_template->x = next_x; item_template->y = top_margin + static_height + static_to_buttons_margin; item_template->cx = button_width; item_template->cy = button_height; item_template->id = ID_BASE + i; next_x += button_width + button_gap; // Move past DLGITEMTEMPLATE structure cursor = (WORD*)(item_template + 1); // Button class *cursor++ = 0xFFFF; *cursor++ = 0x0080; // Title wmemcpy(cursor, button_label[i], button_len[i]); cursor += button_len[i]; *cursor++ = 0; // Empty user data block *cursor++ = 0; } ret_code = DialogBoxIndirect(GetModuleHandle(0), dlg_template, hWnd, NotificationDialogProc); free(buf); return ret_code; }
static LRESULT MultiInputDialog( HINSTANCE hinst, HWND hwndOwner, char * ptext[], int numlines, int width, int tb_cnt, struct textField * tb) { HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; LRESULT ret; int nchar, i; size_t pwid; hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096); if (!hgbl) return -1; mid_cnt = tb_cnt; mid_tb = tb; lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Define a dialog box. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_CENTER | DS_SETFOREGROUND | DS_3DLOOK | DS_SHELLFONT | DS_NOFAILCREATE; lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls lpdt->x = 10; lpdt->y = 10; lpdt->cx = 20 + width * 4; lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14; lpw = (LPWORD) (lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128); lpw += nchar; *lpw++ = 8; // font size (points) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg", -1, lpwsz, 128); lpw += nchar; //----------------------- // Define an OK button. //----------------------- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER; lpdit->dwExtendedStyle = 0; lpdit->x = (lpdt->cx - 14)/4 - 20; lpdit->y = 10 + (numlines + tb_cnt + 2) * 14; lpdit->cx = 40; lpdit->cy = 14; lpdit->id = IDOK; // OK button identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data //----------------------- // Define an Cancel button. //----------------------- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER; lpdit->dwExtendedStyle = 0; lpdit->x = (lpdt->cx - 14)*3/4 - 20; lpdit->y = 10 + (numlines + tb_cnt + 2) * 14; lpdit->cx = 40; lpdit->cy = 14; lpdit->id = IDCANCEL; // CANCEL button identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data /* Add controls for preface data */ for ( i=0; i<numlines; i++) { /*----------------------- * Define a static text control. *-----------------------*/ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; lpdit->dwExtendedStyle = 0; lpdit->x = 10; lpdit->y = 10 + i * 14; lpdit->cx = strlen(ptext[i]) * 4 + 10; lpdit->cy = 14; lpdit->id = ID_TEXT + i; // text identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // static class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i], -1, lpwsz, 2*width); lpw += nchar; *lpw++ = 0; // no creation data } for ( i=0, pwid = 0; i<tb_cnt; i++) { if ( pwid < strlen(tb[i].label) ) pwid = strlen(tb[i].label); } for ( i=0; i<tb_cnt; i++) { /* Prompt */ /*----------------------- * Define a static text control. *-----------------------*/ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; lpdit->dwExtendedStyle = 0; lpdit->x = 10; lpdit->y = 10 + (numlines + i + 1) * 14; lpdit->cx = pwid * 4; lpdit->cy = 14; lpdit->id = ID_TEXT + numlines + i; // text identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // static class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "", -1, lpwsz, 128); lpw += nchar; *lpw++ = 0; // no creation data /*----------------------- * Define an edit control. *-----------------------*/ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD); lpdit->dwExtendedStyle = 0; lpdit->x = 10 + (pwid + 1) * 4; lpdit->y = 10 + (numlines + i + 1) * 14; lpdit->cx = (width - (pwid + 1)) * 4; lpdit->cy = 14; lpdit->id = ID_MID_TEXT + i; // identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0081; // edit class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "", -1, lpwsz, 128); lpw += nchar; *lpw++ = 0; // no creation data } GlobalUnlock(hgbl); ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl, hwndOwner, (DLGPROC) MultiInputDialogProc); GlobalFree(hgbl); switch ( ret ) { case 0: /* Timeout */ return -1; case IDOK: return 1; case IDCANCEL: return 0; default: { char buf[256]; sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError()); MessageBox(hwndOwner, buf, "GetLastError()", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); return -1; } } }
int gui_mch_dialog( int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd) { FARPROC dp; LPWORD p, pnumitems; int numButtons; int *buttonWidths, *buttonPositions; int buttonYpos; int nchar, i; DWORD lStyle; int dlgwidth = 0; int dlgheight; int editboxheight; int horizWidth; int msgheight; char_u *pstart; char_u *pend; char_u *tbuffer; RECT rect; HWND hwnd; HDC hdc; HFONT oldFont; TEXTMETRIC fontInfo; int fontHeight; int textWidth, minButtonWidth, messageWidth; int maxDialogWidth; int vertical; int dlgPaddingX; int dlgPaddingY; HGLOBAL hglbDlgTemp; #ifndef NO_CONSOLE /* Don't output anything in silent mode ("ex -s") */ if (silent_mode) return dfltbutton; /* return default option */ #endif /* If there is no window yet, open it. */ if (s_hwnd == NULL && gui_mch_init() == FAIL) return dfltbutton; if ((type < 0) || (type > VIM_LAST_TYPE)) type = 0; /* allocate some memory for dialog template */ /* TODO should compute this really*/ hglbDlgTemp = GlobalAlloc(GHND, DLG_ALLOC_SIZE); if (hglbDlgTemp == NULL) return -1; p = (LPWORD) GlobalLock(hglbDlgTemp); if (p == NULL) return -1; /* * make a copy of 'buttons' to fiddle with it. compiler grizzles because * vim_strsave() doesn't take a const arg (why not?), so cast away the * const. */ tbuffer = vim_strsave(buttons); if (tbuffer == NULL) return -1; --dfltbutton; /* Change from one-based to zero-based */ /* Count buttons */ numButtons = 1; for (i = 0; tbuffer[i] != '\0'; i++) { if (tbuffer[i] == DLG_BUTTON_SEP) numButtons++; } if (dfltbutton >= numButtons) dfltbutton = 0; /* Allocate array to hold the width of each button */ buttonWidths = (int *) lalloc(numButtons * sizeof(int), TRUE); if (buttonWidths == NULL) return -1; /* Allocate array to hold the X position of each button */ buttonPositions = (int *) lalloc(numButtons * sizeof(int), TRUE); if (buttonPositions == NULL) return -1; /* * Calculate how big the dialog must be. */ hwnd = GetDesktopWindow(); hdc = GetWindowDC(hwnd); oldFont = SelectFont(hdc, GetStockObject(SYSTEM_FONT)); dlgPaddingX = DLG_OLD_STYLE_PADDING_X; dlgPaddingY = DLG_OLD_STYLE_PADDING_Y; GetTextMetrics(hdc, &fontInfo); fontHeight = fontInfo.tmHeight; /* Minimum width for horizontal button */ minButtonWidth = GetTextWidth(hdc, "Cancel", 6); /* Maximum width of a dialog, if possible */ GetWindowRect(s_hwnd, &rect); maxDialogWidth = rect.right - rect.left - GetSystemMetrics(SM_CXFRAME) * 2; if (maxDialogWidth < DLG_MIN_MAX_WIDTH) maxDialogWidth = DLG_MIN_MAX_WIDTH; /* Set dlgwidth to width of message */ pstart = message; messageWidth = 0; msgheight = 0; do { pend = vim_strchr(pstart, DLG_BUTTON_SEP); if (pend == NULL) pend = pstart + STRLEN(pstart); /* Last line of message. */ msgheight += fontHeight; textWidth = GetTextWidth(hdc, pstart, pend - pstart); if (textWidth > messageWidth) messageWidth = textWidth; pstart = pend + 1; } while (*pend != NUL); dlgwidth = messageWidth; /* Add width of icon to dlgwidth, and some space */ dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX; if (msgheight < DLG_ICON_HEIGHT) msgheight = DLG_ICON_HEIGHT; /* * Check button names. A long one will make the dialog wider. */ vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL); if (!vertical) { // Place buttons horizontally if they fit. horizWidth = dlgPaddingX; pstart = tbuffer; i = 0; do { pend = vim_strchr(pstart, DLG_BUTTON_SEP); if (pend == NULL) pend = pstart + STRLEN(pstart); // Last button name. textWidth = GetTextWidth(hdc, pstart, pend - pstart); if (textWidth < minButtonWidth) textWidth = minButtonWidth; textWidth += dlgPaddingX; /* Padding within button */ buttonWidths[i] = textWidth; buttonPositions[i++] = horizWidth; horizWidth += textWidth + dlgPaddingX; /* Pad between buttons */ pstart = pend + 1; } while (*pend != NUL); if (horizWidth > maxDialogWidth) vertical = TRUE; // Too wide to fit on the screen. else if (horizWidth > dlgwidth) dlgwidth = horizWidth; } if (vertical) { // Stack buttons vertically. pstart = tbuffer; do { pend = vim_strchr(pstart, DLG_BUTTON_SEP); if (pend == NULL) pend = pstart + STRLEN(pstart); // Last button name. textWidth = GetTextWidth(hdc, pstart, pend - pstart); textWidth += dlgPaddingX; /* Padding within button */ textWidth += DLG_VERT_PADDING_X * 2; /* Padding around button */ if (textWidth > dlgwidth) dlgwidth = textWidth; pstart = pend + 1; } while (*pend != NUL); } if (dlgwidth < DLG_MIN_WIDTH) dlgwidth = DLG_MIN_WIDTH; /* Don't allow a really thin dialog!*/ /* start to fill in the dlgtemplate information. addressing by WORDs */ lStyle = DS_MODALFRAME | WS_CAPTION | WS_VISIBLE ; add_long(lStyle); pnumitems = p; /*save where the number of items must be stored*/ add_byte(0); // NumberOfItems(will change later) add_word(10); // x add_word(10); // y add_word(PixelToDialogX(dlgwidth)); // Dialog height. if (vertical) dlgheight = msgheight + 2 * dlgPaddingY + DLG_VERT_PADDING_Y + 2 * fontHeight * numButtons; else dlgheight = msgheight + 3 * dlgPaddingY + 2 * fontHeight; // Dialog needs to be taller if contains an edit box. editboxheight = fontHeight + dlgPaddingY + 4 * DLG_VERT_PADDING_Y; if (textfield != NULL) dlgheight += editboxheight; add_word(PixelToDialogY(dlgheight)); add_byte(0); //menu add_byte(0); //class /* copy the title of the dialog */ add_string(title ? title : ("Vim"VIM_VERSION_MEDIUM)); buttonYpos = msgheight + 2 * dlgPaddingY; if (textfield != NULL) buttonYpos += editboxheight; pstart = tbuffer; //dflt_text horizWidth = (dlgwidth - horizWidth) / 2; /* Now it's X offset */ for (i = 0; i < numButtons; i++) { /* get end of this button. */ for ( pend = pstart; *pend && (*pend != DLG_BUTTON_SEP); pend++) ; if (*pend) *pend = '\0'; /* * NOTE: * setting the BS_DEFPUSHBUTTON style doesn't work because Windows sets * the focus to the first tab-able button and in so doing makes that * the default!! Grrr. Workaround: Make the default button the only * one with WS_TABSTOP style. Means user can't tab between buttons, but * he/she can use arrow keys. * * NOTE (Thore): Setting BS_DEFPUSHBUTTON works fine when it's the * first one, so I changed the correct button to be this style. This * is necessary because when an edit box is added, we need a button to * be default. The edit box will be the default control, and when the * user presses enter from the edit box we want the default button to * be pressed. */ if (vertical) { p = add_dialog_element(p, ((i == dfltbutton || dfltbutton < 0) && textfield != NULL ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP, PixelToDialogX(DLG_VERT_PADDING_X), PixelToDialogY(buttonYpos /* TBK */ + 2 * fontHeight * i), PixelToDialogX(dlgwidth - 2 * DLG_VERT_PADDING_X), (WORD)(PixelToDialogY(2 * fontHeight) - 1), (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart); } else { p = add_dialog_element(p, ((i == dfltbutton || dfltbutton < 0) && textfield != NULL ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP, PixelToDialogX(horizWidth + buttonPositions[i]), PixelToDialogY(buttonYpos), /* TBK */ PixelToDialogX(buttonWidths[i]), (WORD)(PixelToDialogY(2 * fontHeight) - 1), (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart); } pstart = pend + 1; /*next button*/ } *pnumitems += numButtons; /* Vim icon */ p = add_dialog_element(p, SS_ICON, PixelToDialogX(dlgPaddingX), PixelToDialogY(dlgPaddingY), PixelToDialogX(DLG_ICON_WIDTH), PixelToDialogY(DLG_ICON_HEIGHT), DLG_NONBUTTON_CONTROL + 0, (BYTE)0x82, &dlg_icons[type]); /* Dialog message */ p = add_dialog_element(p, SS_LEFT, PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH), PixelToDialogY(dlgPaddingY), (WORD)(PixelToDialogX(messageWidth) + 1), PixelToDialogY(msgheight), DLG_NONBUTTON_CONTROL + 1, (BYTE)0x82, message); /* Edit box */ if (textfield != NULL) { p = add_dialog_element(p, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP | WS_BORDER, PixelToDialogX(2 * dlgPaddingX), PixelToDialogY(2 * dlgPaddingY + msgheight), PixelToDialogX(dlgwidth - 4 * dlgPaddingX), PixelToDialogY(fontHeight + dlgPaddingY), DLG_NONBUTTON_CONTROL + 2, (BYTE)0x81, textfield); *pnumitems += 1; } *pnumitems += 2; SelectFont(hdc, oldFont); ReleaseDC(hwnd, hdc); dp = MakeProcInstance((FARPROC)dialog_callback, s_hinst); /* Let the dialog_callback() function know which button to make default * If we have an edit box, make that the default. We also need to tell * dialog_callback() if this dialog contains an edit box or not. We do * this by setting s_textfield if it does. */ if (textfield != NULL) { dialog_default_button = DLG_NONBUTTON_CONTROL + 2; s_textfield = textfield; } else { dialog_default_button = IDCANCEL + 1 + dfltbutton; s_textfield = NULL; } /*show the dialog box modally and get a return value*/ nchar = DialogBoxIndirect( s_hinst, (HGLOBAL) hglbDlgTemp, s_hwnd, (DLGPROC)dp); FreeProcInstance( dp ); GlobalUnlock(hglbDlgTemp); GlobalFree(hglbDlgTemp); vim_free(tbuffer); vim_free(buttonWidths); vim_free(buttonPositions); return nchar; }