Używanie typowych okien dialogowych
W tej sekcji omówiono zadania, które wywołują typowe okna dialogowe:
- Wybieranie koloru
- Wybieranie Czcionki
- Otwieranie pliku
- Wyświetlanie Okna Dialogowego Drukowania
- używanie arkusza właściwości drukowania
- Konfigurowanie Drukowanej Strony
- Znajdowanie Tekstu
Wybieranie koloru
W tym temacie opisano przykładowy kod, który wyświetla okno dialogowe Color, dzięki czemu użytkownik może wybrać kolor. Przykładowy kod najpierw inicjuje strukturę CHOOSECOLOR, a następnie wywołuje funkcję ChooseColor, aby wyświetlić okno dialogowe. Jeśli funkcja zwróci true, wskazując, że użytkownik wybrał kolor, przykładowy kod używa wybranego koloru, aby utworzyć nowy solidny pędzl.
W tym przykładzie użyto struktury CHOOSECOLOR, aby zainicjować okno dialogowe w następujący sposób:
- Inicjuje element członkowski lpCustColors z wskaźnikiem do statycznej tablicy wartości. Kolory w tablicy są początkowo czarne, ale tablica statyczna zachowuje niestandardowe kolory utworzone przez użytkownika na potrzeby kolejnych wywołań ChooseColor.
- Ustawia flagę CC_RGBINIT i inicjuje pole rgbResult, aby określić kolor, który jest domyślnie wybrany po otwarciu okna dialogowego. Jeśli nie zostanie określony, początkowy wybór to czarny. W przykładzie użyto zmiennej statycznej rgbCurrent, aby zachować wybraną wartość między wywołaniami ChooseColor.
- Ustawia flagę CC_FULLOPEN, aby rozszerzenie niestandardowych kolorów okna dialogowego było zawsze wyświetlane.
CHOOSECOLOR cc; // common dialog box structure
static COLORREF acrCustClr[16]; // array of custom colors
HWND hwnd; // owner window
HBRUSH hbrush; // brush handle
static DWORD rgbCurrent; // initial color selection
// Initialize CHOOSECOLOR
ZeroMemory(&cc, sizeof(cc));
cc.lStructSize = sizeof(cc);
cc.hwndOwner = hwnd;
cc.lpCustColors = (LPDWORD) acrCustClr;
cc.rgbResult = rgbCurrent;
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
if (ChooseColor(&cc)==TRUE)
{
hbrush = CreateSolidBrush(cc.rgbResult);
rgbCurrent = cc.rgbResult;
}
Wybieranie czcionki
W tym temacie opisano przykładowy kod, który wyświetla okno dialogowe Czcionka, aby użytkownik mógł wybrać atrybuty czcionki. Przykładowy kod najpierw inicjuje strukturę CHOOSEFONT, a następnie wywołuje funkcję ChooseFont, aby wyświetlić okno dialogowe.
W tym przykładzie ustawiono flagę CF_SCREENFONTS, aby określić, że okno dialogowe powinno wyświetlać tylko czcionki ekranu. Ustawia flagę CF_EFFECTS do wyświetlania kontrolek, które umożliwiają użytkownikowi wybieranie opcji przekreślenia, podkreślenia i koloru.
Jeśli ChooseFont zwraca TRUE, wskazując, że użytkownik kliknął przycisk OK, struktura CHOOSEFONT zawiera informacje opisujące czcionkę i jej atrybuty wybrane przez użytkownika, w tym członków struktury LOGFONT wskazywanych przez element członkowski lpLogFont. Składowa rgbColors zawiera zaznaczony kolor tekstu. Przykładowy kod używa tych informacji do ustawienia czcionki i koloru tekstu dla kontekstu urządzenia skojarzonego z oknem właściciela.
HWND hwnd; // owner window
HDC hdc; // display device context of owner window
CHOOSEFONT cf; // common dialog box structure
static LOGFONT lf; // logical font structure
static DWORD rgbCurrent; // current text color
HFONT hfont, hfontPrev;
DWORD rgbPrev;
// Initialize CHOOSEFONT
ZeroMemory(&cf, sizeof(cf));
cf.lStructSize = sizeof (cf);
cf.hwndOwner = hwnd;
cf.lpLogFont = &lf;
cf.rgbColors = rgbCurrent;
cf.Flags = CF_SCREENFONTS | CF_EFFECTS;
if (ChooseFont(&cf)==TRUE)
{
hfont = CreateFontIndirect(cf.lpLogFont);
hfontPrev = SelectObject(hdc, hfont);
rgbCurrent= cf.rgbColors;
rgbPrev = SetTextColor(hdc, rgbCurrent);
.
.
.
}
Otwieranie pliku
Notatka
Począwszy od systemu Windows Vista, Wspólne Okno Dialogowe Pliku zostało zastąpione przez Wspólne Okno Dialogowe Elementów podczas otwierania plików. Zalecamy użycie interfejsu API okna dialogowego wspólnego elementu zamiast interfejsu API okna dialogowego wspólnego pliku. Aby uzyskać więcej informacji, zobacz okno dialogowe wspólnego elementu .
W tym temacie opisano przykładowy kod, który wyświetla Otwórz okno dialogowe, aby użytkownik mógł określić dysk, katalog i nazwę pliku do otwarcia. Przykładowy kod najpierw inicjuje strukturę OPENFILENAME, a następnie wywołuje funkcję GetOpenFileName, aby wyświetlić okno dialogowe.
W tym przykładzie element członkowski lpstrFilter jest wskaźnikiem do buforu, który określa dwa filtry nazw plików, które użytkownik może wybrać, aby ograniczyć wyświetlane nazwy plików. Bufor zawiera tablicę ciągów znaków o podwójnie zakończonej wartości null, gdzie każda para ciągów znaków określa filtr. Element członkowski nFilterIndex określa, że pierwszy wzorzec jest używany podczas tworzenia okna dialogowego.
W tym przykładzie ustawiono flagi OFN_PATHMUSTEXIST i OFN_FILEMUSTEXIST w elemencie Flags. Te flagi powodują, że przed zwróceniem okna dialogowego zostanie zweryfikowane, że ścieżka i nazwa pliku określona przez użytkownika rzeczywiście istnieją.
Funkcja GetOpenFileName zwraca true, jeśli użytkownik kliknie przycisk OK, a określona ścieżka i nazwa pliku istnieją. W tym przypadku bufor wskazywany przez element członkowski lpstrFile zawiera ścieżkę i nazwę pliku. Przykładowy kod używa tych informacji w wywołaniu funkcji w celu otwarcia pliku.
Mimo że w tym przykładzie nie ustawiono flagi OFN_EXPLORER, nadal jest wyświetlany domyślny styl Eksploratora Otwórz okno dialogowe. Jeśli jednak chcesz podać procedurę hook lub niestandardowy szablon i chcesz używać interfejsu użytkownika Eksploratora, musisz ustawić flagę OFN_EXPLORER.
Notatka
W języku programowania C ciąg ujęty w cudzysłowie jest zakończony znakiem null.
OPENFILENAME ofn; // common dialog box structure
char szFile[260]; // buffer for file name
HWND hwnd; // owner window
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn)==TRUE)
hf = CreateFile(ofn.lpstrFile,
GENERIC_READ,
0,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
Wyświetlanie okna dialogowego Drukowanie
W tym temacie opisano przykładowy kod, który wyświetla okno dialogowe Drukuj, dzięki czemu użytkownik może wybrać opcje drukowania dokumentu. Przykładowy kod najpierw inicjuje strukturę PRINTDLG, a następnie wywołuje funkcję PrintDlg, aby wyświetlić okno dialogowe.
W tym przykładzie ustawiono flagę PD_RETURNDC w Flagi składowej struktury PRINTDLG. Powoduje to, że PrintDlg zwraca uchwyt kontekstu urządzenia dla wybranej drukarki w elemencie członkowskim hDC. Uchwyt umożliwia renderowanie danych wyjściowych na drukarce.
Na wejściu, przykładowy kod ustawia członków hDevMode i hDevNames na NULL. Jeśli funkcja zwraca TRUE, ci członkowie zwracają uchwyty do struktur DEVNAMES, które zawierają dane wejściowe użytkownika i informacje o drukarce. Te informacje umożliwiają przygotowanie danych wyjściowych do wysłania do wybranej drukarki.
PRINTDLG pd;
HWND hwnd;
// Initialize PRINTDLG
ZeroMemory(&pd, sizeof(pd));
pd.lStructSize = sizeof(pd);
pd.hwndOwner = hwnd;
pd.hDevMode = NULL; // Don't forget to free or store hDevMode.
pd.hDevNames = NULL; // Don't forget to free or store hDevNames.
pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
pd.nCopies = 1;
pd.nFromPage = 0xFFFF;
pd.nToPage = 0xFFFF;
pd.nMinPage = 1;
pd.nMaxPage = 0xFFFF;
if (PrintDlg(&pd)==TRUE)
{
// GDI calls to render output.
// Delete DC when done.
DeleteDC(pd.hDC);
}
Korzystanie z arkusza właściwości drukowania
W tym temacie opisano przykładowy kod, który wyświetla arkusz właściwości Print, dzięki czemu użytkownik może wybrać opcje drukowania dokumentu. Przykładowy kod najpierw inicjuje strukturę PRINTDLGEX, a następnie wywołuje funkcję PrintDlgEx, aby wyświetlić arkusz właściwości.
Przykładowy kod ustawia flagę PD_RETURNDC w Flags składowej struktury PRINTDLG. Powoduje to, że funkcja PrintDlgEx zwraca uchwyt kontekstu urządzenia do wybranej drukarki w elemencie hDC.
Na wejściu przykładowy kod ustawia hDevMode i składowe hDevNames na NULL. Jeśli funkcja zwróci S_OK, ci członkowie zwracają uchwyty do struktury DEVNAMES zawierającej dane wejściowe użytkownika i informacje o drukarce. Te informacje umożliwiają przygotowanie danych wyjściowych do wysłania do wybranej drukarki.
Po zakończeniu operacji drukowania przykładowy kod zwalnia bufory DEVMODE, DEVNAMES, PRINTPAGERANGE, i wywołuje funkcję DeleteDC w celu usunięcia kontekstu urządzenia.
// hWnd is the window that owns the property sheet.
HRESULT DisplayPrintPropertySheet(HWND hWnd)
{
HRESULT hResult;
PRINTDLGEX pdx = {0};
LPPRINTPAGERANGE pPageRanges = NULL;
// Allocate an array of PRINTPAGERANGE structures.
pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
if (!pPageRanges)
return E_OUTOFMEMORY;
// Initialize the PRINTDLGEX structure.
pdx.lStructSize = sizeof(PRINTDLGEX);
pdx.hwndOwner = hWnd;
pdx.hDevMode = NULL;
pdx.hDevNames = NULL;
pdx.hDC = NULL;
pdx.Flags = PD_RETURNDC | PD_COLLATE;
pdx.Flags2 = 0;
pdx.ExclusionFlags = 0;
pdx.nPageRanges = 0;
pdx.nMaxPageRanges = 10;
pdx.lpPageRanges = pPageRanges;
pdx.nMinPage = 1;
pdx.nMaxPage = 1000;
pdx.nCopies = 1;
pdx.hInstance = 0;
pdx.lpPrintTemplateName = NULL;
pdx.lpCallback = NULL;
pdx.nPropertyPages = 0;
pdx.lphPropertyPages = NULL;
pdx.nStartPage = START_PAGE_GENERAL;
pdx.dwResultAction = 0;
// Invoke the Print property sheet.
hResult = PrintDlgEx(&pdx);
if ((hResult == S_OK) && pdx.dwResultAction == PD_RESULT_PRINT)
{
// User clicked the Print button, so use the DC and other information returned in the
// PRINTDLGEX structure to print the document.
}
if (pdx.hDevMode != NULL)
GlobalFree(pdx.hDevMode);
if (pdx.hDevNames != NULL)
GlobalFree(pdx.hDevNames);
if (pdx.lpPageRanges != NULL)
GlobalFree(pPageRanges);
if (pdx.hDC != NULL)
DeleteDC(pdx.hDC);
return hResult;
}
Konfigurowanie strony drukowanej
W tym temacie opisano przykładowy kod, który wyświetla okno dialogowe ustawień strony (), aby użytkownik mógł wybrać atrybuty strony drukowanej, takie jak typ papieru, źródło papieru, orientacja strony i marginesy strony. Przykładowy kod najpierw inicjuje strukturę PAGESETUPDLG, a następnie wywołuje funkcję PageSetupDlg w celu wyświetlenia okna dialogowego.
W tym przykładzie ustawiono flagę PSD_MARGINS w elemencie Flags i użyto elementu rtMargin w celu określenia początkowych wartości marginesu. Ustawia flagę PSD_INTHOUSANDTHSOFINCHES, aby upewnić się, że okno dialogowe wyraża wymiary marginesu w tysiącach cala.
W danych wejściowych przykładowy kod ustawia hDevMode i elementy członkowskie hDevNames na null. Jeśli funkcja zwraca TRUE, to używa tych elementów członkowskich do zwracania dojść do struktur DEVNAMES zawierających dane wejściowe użytkownika i informacje o drukarce. Te informacje umożliwiają przygotowanie danych wyjściowych do wysłania do wybranej drukarki.
Poniższy przykład umożliwia również PagePaintHook procedurę zaczepienia w celu dostosowania zawartości strony przykładowej.
PAGESETUPDLG psd; // common dialog box structure
HWND hwnd; // owner window
// Initialize PAGESETUPDLG
ZeroMemory(&psd, sizeof(psd));
psd.lStructSize = sizeof(psd);
psd.hwndOwner = hwnd;
psd.hDevMode = NULL; // Don't forget to free or store hDevMode.
psd.hDevNames = NULL; // Don't forget to free or store hDevNames.
psd.Flags = PSD_INTHOUSANDTHSOFINCHES | PSD_MARGINS |
PSD_ENABLEPAGEPAINTHOOK;
psd.rtMargin.top = 1000;
psd.rtMargin.left = 1250;
psd.rtMargin.right = 1250;
psd.rtMargin.bottom = 1000;
psd.lpfnPagePaintHook = PaintHook;
if (PageSetupDlg(&psd)==TRUE)
{
// check paper size and margin values here.
}
Poniższy przykład przedstawia przykładową procedurę haka PagePaintHook, która rysuje prostokąt marginesu w przykładowym obszarze strony.
BOOL CALLBACK PaintHook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPRECT lprc;
COLORREF crMargRect;
HDC hdc, hdcOld;
switch (uMsg)
{
// Draw the margin rectangle.
case WM_PSD_MARGINRECT:
hdc = (HDC) wParam;
lprc = (LPRECT) lParam;
// Get the system highlight color.
crMargRect = GetSysColor(COLOR_HIGHLIGHT);
// Create a dash-dot pen of the system highlight color and
// select it into the DC of the sample page.
hdcOld = SelectObject(hdc, CreatePen(PS_DASHDOT, .5, crMargRect));
// Draw the margin rectangle.
Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
// Restore the previous pen to the DC.
SelectObject(hdc, hdcOld);
return TRUE;
default:
return FALSE;
}
return TRUE;
}
Znajdowanie tekstu
W tym temacie opisano przykładowy kod, który wyświetla i zarządza oknem dialogowym znajdowanie, aby użytkownik mógł określić parametry operacji wyszukiwania. Okno dialogowe wysyła komunikaty do procedury okna, aby można było wykonać operację wyszukiwania.
Kod do wyświetlania i zarządzania oknem dialogowym Replace jest podobny, z tą różnicą, że używa funkcji ReplaceText do jego wyświetlania. Zamień okno dialogowe wysyła również komunikaty w odpowiedzi na kliknięcia użytkownika na Zastąp i Zastąp wszystkie przyciski.
Aby użyć okna dialogowego Znajdź lub Zamień, należy wykonać trzy oddzielne zadania:
- Pobierz identyfikator wiadomości zarejestrowanej FINDMSGSTRING.
- Wyświetl okno dialogowe.
- Przetwarzanie komunikatów FINDMSGSTRING po otwarciu okna dialogowego.
Po zainicjowaniu aplikacji wywołaj funkcję RegisterWindowMessage, aby uzyskać identyfikator komunikatu zarejestrowanej wiadomości FINDMSGSTRING.
UINT uFindReplaceMsg; // message identifier for FINDMSGSTRING
uFindReplaceMsg = RegisterWindowMessage(FINDMSGSTRING);
Aby wyświetlić okno dialogowe Znajdź, najpierw zainicjuj strukturę FINDREPLACE, a następnie wywołaj funkcję FindText. Należy pamiętać, że struktura FINDREPLACE i bufor ciągu wyszukiwania powinien być zmienną globalną lub statyczną, aby nie wykraczała poza zakres przed zamknięciem okna dialogowego. Należy ustawić element członkowski hwndOwner, aby określić okno odbierające zarejestrowane komunikaty. Po utworzeniu okna dialogowego możesz przenieść go lub manipulować nim przy użyciu zwróconego uchwytu.
FINDREPLACE fr; // common dialog box structure
HWND hwnd; // owner window
CHAR szFindWhat[80]; // buffer receiving string
HWND hdlg = NULL; // handle to Find dialog box
// Initialize FINDREPLACE
ZeroMemory(&fr, sizeof(fr));
fr.lStructSize = sizeof(fr);
fr.hwndOwner = hwnd;
fr.lpstrFindWhat = szFindWhat;
fr.wFindWhatLen = 80;
fr.Flags = 0;
hdlg = FindText(&fr);
Po otwarciu okna dialogowego główna pętla komunikatów musi zawierać wywołanie funkcji IsDialogMessage. Przekaż uchwyt do okna dialogowego jako parametr w wywołaniu IsDialogMessage. Dzięki temu okno dialogowe prawidłowo przetwarza komunikaty klawiaturowe.
Aby monitorować komunikaty wysyłane z okna dialogowego, procedura dla okna musi sprawdzić zarejestrowany komunikat FINDMSGSTRING i przetworzyć wartości przekazane w strukturze FINDREPLACE, zgodnie z poniższym przykładem.
LPFINDREPLACE lpfr;
if (message == uFindReplaceMsg)
{
// Get pointer to FINDREPLACE structure from lParam.
lpfr = (LPFINDREPLACE)lParam;
// If the FR_DIALOGTERM flag is set,
// invalidate the handle that identifies the dialog box.
if (lpfr->Flags & FR_DIALOGTERM)
{
hdlg = NULL;
return 0;
}
// If the FR_FINDNEXT flag is set,
// call the application-defined search routine
// to search for the requested string.
if (lpfr->Flags & FR_FINDNEXT)
{
SearchFile(lpfr->lpstrFindWhat,
(BOOL) (lpfr->Flags & FR_DOWN),
(BOOL) (lpfr->Flags & FR_MATCHCASE));
}
return 0;
}