Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

955 lines
26 KiB

// Common Control Sample app [mikesh]
//
#include "ccontrol.h"
#include "resource.h"
#ifdef _DEBUG
#define DEBUG
#endif
#ifdef DEBUG
void ODS(LPCSTR fmt, ...)
{
char buf[5*MAX_PATH];
wvsprintf(buf, fmt, (LPVOID)(&fmt+1));
lstrcat(buf, "\r\n");
OutputDebugString(buf);
}
#else
#define ODS 1 ? (void)0 : (void)
#endif
HINSTANCE g_hinst;
#define MAX_PROP_PAGES 12
typedef struct tagGLOBALINFO {
int nPages; // count of pages
BOOL fNeedToSave; // TRUE when info needs to be saved
// Here's the apply scheme:
// when we realize we need to save info, set fNeedToSave to true.
// when apply is pressed and the flag is set, save and clear the flag.
// when apply is pressed and the flag is clear, do nothing.
// This avoids saving info multiple times (on each PSN_APPLY)
// Of course, this sample doesn't save anything, but this logic
// was in the code I grabbed this from.
HWND hwndDT; // DateTime window on Date and Time page
HWND hwndMC; // MonthCal window on MonthCal page
HWND hwndMCWrap; // Window which contains hwndMC
RECT rcMCWrap;
DWORD mcFlags;
DWORD dwSelRange;
} GLOBALINFO, *PGLOBALINFO;
// Each page gets one of these
typedef struct tagPAGEINFO {
PROPSHEETPAGE psp; // prop sheet page description
PGLOBALINFO pgi; // pointer to shared sheet info
} PAGEINFO, * PPAGEINFO;
//
// function prototypes
//
void AddPropPage(UINT, DLGPROC, PGLOBALINFO, LPPROPSHEETHEADER);
BOOL CALLBACK WelcomeDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DateTimeDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK MonthCalDlgProc(HWND, UINT, WPARAM, LPARAM);
//
// our code
//
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HPROPSHEETPAGE ahpage[MAX_PROP_PAGES];
PROPSHEETHEADER psh;
GLOBALINFO gi;
INITCOMMONCONTROLSEX icce;
ODS("Sample: started");
icce.dwSize = sizeof(icce);
icce.dwICC = ICC_DATE_CLASSES;
InitCommonControlsEx(&icce);
g_hinst = hInstance;
ZeroMemory(&gi, sizeof(gi));
ZeroMemory(&psh, sizeof(psh));
psh.dwSize = sizeof(psh);
psh.dwFlags = PSH_DEFAULT|PSH_NOAPPLYNOW;
psh.hInstance = g_hinst;
psh.pszCaption = "Common Control Samples";
psh.phpage = ahpage;
if (lpCmdLine && *lpCmdLine)
{
// Let the user specify the starting page thru the command line
psh.dwFlags |= PSH_USEPSTARTPAGE;
psh.pStartPage = (LPCTSTR)lpCmdLine;
}
AddPropPage(IDD_WELCOME, WelcomeDlgProc, &gi, &psh);
AddPropPage(IDD_DATEANDTIME, DateTimeDlgProc, &gi, &psh);
AddPropPage(IDD_MONTHCAL, MonthCalDlgProc, &gi, &psh);
gi.nPages = psh.nPages;
ODS("Sample: %d pages", gi.nPages);
PropertySheet(&psh);
return(1);
}
void AddPropPage(UINT idResource,
DLGPROC lpfnDlgProc,
PGLOBALINFO pgi,
LPPROPSHEETHEADER ppsh)
{
if (ppsh->nPages < MAX_PROP_PAGES)
{
PAGEINFO pi;
HPROPSHEETPAGE hpage;
ZeroMemory(&pi, sizeof(PAGEINFO));
// Fill common part
pi.psp.dwSize = sizeof(pi); // extra data
pi.psp.dwFlags = PSP_DEFAULT;
pi.psp.hInstance = g_hinst;
pi.psp.pszTemplate = MAKEINTRESOURCE(idResource);
pi.psp.pfnDlgProc = lpfnDlgProc;
// Fill extra parameter
pi.pgi = pgi;
hpage = CreatePropertySheetPage(&pi.psp);
if (hpage)
{
ppsh->phpage[ppsh->nPages++] = hpage;
}
}
}
BOOL CALLBACK WelcomeDlgProc(HWND hdlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
switch (uMessage)
{
case WM_NOTIFY:
switch (((NMHDR *)lParam)->code)
{
case PSN_KILLACTIVE:
case PSN_APPLY:
case PSN_SETACTIVE:
// this page really doesn't do anything
SetWindowLong(hdlg, DWL_MSGRESULT, 0);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
} // switch
return TRUE;
}
/*
** DateTimeer common controls
*/
static const char szDateTimeClass[] = DATETIMEPICK_CLASS;
VOID PASCAL CreateDateTime(HWND hdlg, PPAGEINFO ppi)
{
DWORD dwStyle = 0;
DWORD dwExStyle = 0;
int dy = 0;
if (IsDlgButtonChecked(hdlg,IDC_UPDOWN)) dwStyle |= DTS_UPDOWN;
if (IsDlgButtonChecked(hdlg,IDC_SHOWNONE)) dwStyle |= DTS_SHOWNONE;
if (IsDlgButtonChecked(hdlg,IDC_LONGDATEFORMAT)) dwStyle |= DTS_LONGDATEFORMAT;
if (IsDlgButtonChecked(hdlg,IDC_TIMEFORMAT)) dwStyle |= DTS_TIMEFORMAT;
if (IsDlgButtonChecked(hdlg,IDC_APPCANPARSE)) dwStyle |= DTS_APPCANPARSE;
if (IsDlgButtonChecked(hdlg,IDC_RIGHTALIGN)) dwStyle |= DTS_RIGHTALIGN;
if (IsDlgButtonChecked(hdlg,IDC_WS_BORDER)) dwStyle |= WS_BORDER, dy += 2;
if (IsDlgButtonChecked(hdlg,IDC_WS_DLGFRAME)) dwStyle |= WS_DLGFRAME, dy += 6;
if (IsDlgButtonChecked(hdlg,IDC_WS_THICKFRAME)) dwStyle |= WS_THICKFRAME, dy += 6;
if (IsDlgButtonChecked(hdlg,IDC_WS_EX_CLIENTEDGE)) dwExStyle |= WS_EX_CLIENTEDGE, dy += 4;
if (IsDlgButtonChecked(hdlg,IDC_WS_EX_DLGMODALFRAME)) dwExStyle |= WS_EX_DLGMODALFRAME, dy += 6;
if (IsDlgButtonChecked(hdlg,IDC_WS_EX_STATICEDGE)) dwExStyle |= WS_EX_STATICEDGE, dy += 2;
if (IsDlgButtonChecked(hdlg,IDC_WS_EX_WINDOWEDGE)) dwExStyle |= WS_EX_WINDOWEDGE;
ppi->pgi->hwndDT = CreateWindowEx(dwExStyle, szDateTimeClass, "DateTime",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | dwStyle,
28, 185, 159, 18+dy,
hdlg, NULL, g_hinst, NULL);
if (ppi->pgi->hwndDT)
{
char sz[80];
SetDlgItemText(hdlg, IDC_STATIC_DATE, "<not modified>");
GetDlgItemText(hdlg, IDC_DT_FORMATSTRING, sz, sizeof(sz));
DateTime_SetFormat(ppi->pgi->hwndDT, sz);
}
else
{
ODS("Sample: ERROR - could not create DateTime window");
}
}
static int rgnAccumDaysPerMonth[] = {
0, // remember, everything's offset cuz the first month hasn't accumulated any days yet...
31, // Jan
59, // Feb
90, // Mar
120, // Apr
151, // May
181, // Jun
212, // Jul
243, // Aug
273, // Sep
304, // Oct
334, // Nov
365 // Dec
};
static int rgnAccumDaysPerMonthLeap[] = {
0, // remember, everything's offset cuz the first month hasn't accumulated any days yet...
31, // Jan
60, // Feb
91, // Mar
121, // Apr
152, // May
182, // Jun
213, // Jul
244, // Aug
274, // Sep
305, // Oct
335, // Nov
366 // Dec
};
BOOL CALLBACK DateTimeDlgProc(HWND hdlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
PPAGEINFO ppi = (PPAGEINFO)GetWindowLong(hdlg, DWL_USER);
switch (uMessage)
{
case WM_INITDIALOG:
ppi = (PPAGEINFO)lParam;
SetWindowLong(hdlg, DWL_USER, lParam);
CheckDlgButton(hdlg, IDC_WS_EX_CLIENTEDGE, BST_CHECKED);
CreateDateTime(hdlg, ppi);
break;
case WM_WININICHANGE:
// This control cares about locale changes
if (ppi) // can I get this before my dialog has been created? Be safe.
return SendMessage(ppi->pgi->hwndDT, uMessage, wParam, lParam);
break;
case WM_COMMAND:
{
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_UPDOWN:
case IDC_SHOWNONE:
case IDC_LONGDATEFORMAT:
case IDC_TIMEFORMAT:
case IDC_APPCANPARSE:
case IDC_RIGHTALIGN:
case IDC_WS_BORDER:
case IDC_WS_DLGFRAME:
case IDC_WS_THICKFRAME:
case IDC_WS_EX_CLIENTEDGE:
case IDC_WS_EX_DLGMODALFRAME:
case IDC_WS_EX_STATICEDGE:
case IDC_WS_EX_WINDOWEDGE:
// Change the DateTimeer
DestroyWindow(ppi->pgi->hwndDT);
ppi->pgi->hwndDT = NULL;
CreateDateTime(hdlg, ppi);
break;
case IDC_DT_FORMATSTRING:
if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
{
char sz[80];
GetDlgItemText(hdlg, IDC_DT_FORMATSTRING, sz, sizeof(sz));
DateTime_SetFormat(ppi->pgi->hwndDT, sz);
}
break;
}
break;
}
case WM_NOTIFY:
switch (((NMHDR *)lParam)->code)
{
case PSN_KILLACTIVE:
case PSN_APPLY:
case PSN_SETACTIVE:
// this page really doesn't do anything
SetWindowLong(hdlg, DWL_MSGRESULT, 0);
break;
case DTN_DATETIMECHANGE:
{
LPNMDATETIMECHANGE lpnmdtc = (LPNMDATETIMECHANGE)lParam;
char szBuf[160];
if (lpnmdtc->dwFlags == GDT_NONE)
{
lstrcpy(szBuf, "<none>");
}
else
{
char szDate[80];
char szTime[80];
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &lpnmdtc->st, NULL, szDate, sizeof(szDate));
GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT, &lpnmdtc->st, NULL, szTime, sizeof(szTime));
wsprintf(szBuf, "%s %s", szDate, szTime);
}
SetDlgItemText(hdlg, IDC_STATIC_DATE, szBuf);
SendMessage(ppi->pgi->hwndDT, WM_GETTEXT, 20, (LPARAM)szBuf); // only get first 20 chars
ODS("Sample: WM_GETTEXT [%s] len=%d", szBuf, SendMessage(ppi->pgi->hwndDT, WM_GETTEXTLENGTH, 0, 0));
break;
}
case DTN_USERSTRING:
{
LPNMDATETIMESTRING lpnmdts = (LPNMDATETIMESTRING)lParam;
// Heck, I don't know how to parse anything... Arbitrarily set it to 4 DEC 69.
ZeroMemory(&lpnmdts->st, sizeof(lpnmdts->st));
lpnmdts->st.wDay = 4;
lpnmdts->st.wMonth = 12;
lpnmdts->st.wYear = 1969;
break;
}
// The following three notifications are for handling application provided format strings.
// Application provided format strings are of the format "X" "XX" "XXX" or "XXXX...".
// For these strings, an application handles their modification as well as their display.
//
// For this sample, let "X" be WEEK OF YEAR and "XX" be YEAR
case DTN_WMKEYDOWN:
{
LPNMDATETIMEWMKEYDOWN pnmdtkd = (LPNMDATETIMEWMKEYDOWN)lParam;
int delta;
delta = 1;
switch (pnmdtkd->nVirtKey)
{
case VK_DOWN:
case VK_SUBTRACT:
delta = -1;
// fall through
case VK_UP:
case VK_ADD:
if (!lstrcmp(pnmdtkd->pszFormat, "XX") ||
!lstrcmp(pnmdtkd->pszFormat, "XXXX") ) // year
{
pnmdtkd->st.wYear += delta;
}
else if (!lstrcmp(pnmdtkd->pszFormat, "X")) // week of year
{
int *pnAccum;
int nDayOfYear;
// moving by weeks is tough, convert to day-of-year (adjust for leap year) and back again
if ((pnmdtkd->st.wYear & 0x0003) == 0 &&
(pnmdtkd->st.wYear <= 1750 ||
pnmdtkd->st.wYear % 100 != 0 ||
pnmdtkd->st.wYear % 400 == 0))
{
pnAccum = rgnAccumDaysPerMonthLeap;
}
else
{
pnAccum = rgnAccumDaysPerMonth;
}
nDayOfYear = pnmdtkd->st.wDay + pnAccum[pnmdtkd->st.wMonth-1] + delta * 7;
if (nDayOfYear <= 0)
{
pnmdtkd->st.wYear--;
pnmdtkd->st.wMonth = 12;
pnmdtkd->st.wDay = 31 + nDayOfYear;
}
else if (nDayOfYear > pnAccum[12])
{
pnmdtkd->st.wYear++;
pnmdtkd->st.wMonth = 1;
pnmdtkd->st.wDay = nDayOfYear - pnAccum[12];
}
else
{
int i = 1;
while (pnAccum[i] < nDayOfYear)
{
i++;
}
pnmdtkd->st.wMonth = i;
pnmdtkd->st.wDay = nDayOfYear - pnAccum[i-1];
}
}
ODS("CControl: DTN_WMKEYDOWN results in wDay=%d wMonth=%d wYear=%d", pnmdtkd->st.wDay, pnmdtkd->st.wMonth, pnmdtkd->st.wYear);
}
break;
} // DTN_WMKEYDOWN
case DTN_FORMATQUERY:
{
LPNMDATETIMEFORMATQUERY pnmdtfq = (LPNMDATETIMEFORMATQUERY)lParam;
HDC hdc;
HFONT hfont, hfontOrig;
LPSTR psz;
#ifdef DEBUG
LPCSTR pszQuery;
#endif
hfont = FORWARD_WM_GETFONT(ppi->pgi->hwndDT, SendMessage);
if (hfont == NULL)
hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
hdc = GetDC(hdlg);
hfontOrig = SelectObject(hdc, hfont);
if (!lstrcmp("X", pnmdtfq->pszFormat))
{
#ifdef DEBUG
pszQuery = "day-of-year";
#endif
psz = "52";
}
else if (!lstrcmp("XX", pnmdtfq->pszFormat))
{
#ifdef DEBUG
pszQuery = "year";
#endif
psz = "95";
}
else if (!lstrcmp("XXXX", pnmdtfq->pszFormat))
{
#ifdef DEBUG
pszQuery = "full year";
#endif
psz = "1995";
}
else
{
#ifdef DEBUG
pszQuery = pnmdtfq->pszFormat;
#endif
psz = "";
}
GetTextExtentPoint32(hdc, psz, lstrlen(psz), &pnmdtfq->szMax);
#ifdef DEBUG
ODS("CControl DTN_FORMATQUERY [%s] results in w=%d", pszQuery, pnmdtfq->szMax.cx);
#endif
SelectObject(hdc, hfontOrig);
ReleaseDC(hdlg, hdc);
break;
} // DTN_FORMATQUERY
case DTN_FORMAT:
{
LPNMDATETIMEFORMAT pnmdtf = (LPNMDATETIMEFORMAT)lParam;
int nWeek, nYear;
int *pnAccum;
int nDayOfYear;
// calculating week of year is tough...
if ((pnmdtf->st.wYear & 0x0003) == 0 &&
(pnmdtf->st.wYear <= 1750 ||
pnmdtf->st.wYear % 100 != 0 ||
pnmdtf->st.wYear % 400 == 0) )
{
pnAccum = rgnAccumDaysPerMonthLeap;
}
else
{
pnAccum = rgnAccumDaysPerMonth;
}
nDayOfYear = pnmdtf->st.wDay + pnAccum[pnmdtf->st.wMonth-1];
// BUGBUG: this is too hard to do in my sample app, just divide by 7
nYear = pnmdtf->st.wYear;
nWeek = nDayOfYear / 7 + 1;
if (nWeek > 52)
{
nWeek = 1;
nYear++;
}
if (!lstrcmp("X", pnmdtf->pszFormat))
{
wsprintf(pnmdtf->szDisplay, "%02d", nWeek);
ODS("CControl: DTN_FORMAT day-of-year results in [%s]", pnmdtf->szDisplay);
}
else if (!lstrcmp("XX", pnmdtf->pszFormat))
{
wsprintf(pnmdtf->szDisplay, "%02d", nYear % 100);
ODS("CControl: DTN_FORMAT year results in [%s]", pnmdtf->szDisplay);
}
else if (!lstrcmp("XXXX", pnmdtf->pszFormat))
{
wsprintf(pnmdtf->szDisplay, "%d", nYear);
ODS("CControl: DTN_FORMAT full year results in [%s]", pnmdtf->szDisplay);
}
else
{
pnmdtf->szDisplay[0] = '\0';
ODS("CControl: DTN_FORMAT unrecognized results in [%s]", pnmdtf->szDisplay);
}
break;
} // DTN_FORMAT
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
/*
** MonthCal common control
*/
static const char szMonthCalClass[] = MONTHCAL_CLASS;
static const char szMonthCalWrapClass[] = "MCWrap";
LRESULT MCWrapWndProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
PPAGEINFO ppi = (PPAGEINFO)GetWindowLong(hwnd, 0);
if (uMessage == WM_CREATE)
{
LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
SetWindowLong(hwnd, 0, (long)(lpcs->lpCreateParams));
ppi = (PPAGEINFO)lpcs->lpCreateParams;
ppi->pgi->hwndMC = CreateWindowEx(0, szMonthCalClass, "MonthCal1",
WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | ppi->pgi->mcFlags,
0, 0, 0, 0, // resize it when we know how big it will be
hwnd, NULL, g_hinst, NULL);
if (!ppi->pgi->hwndMC)
{
ODS("Sample: ERROR - could not create MonthCal window!");
return(-1);
}
return(0);
}
if (ppi == NULL || ppi->pgi->hwndMC == NULL)
return(DefWindowProc(hwnd, uMessage, wParam, lParam));
switch (uMessage) {
case WM_DESTROY:
DestroyWindow(ppi->pgi->hwndMC);
ppi->pgi->hwndMC = NULL;
return(0);
case WM_SIZE:
{
int width, height;
width = LOWORD(lParam);
height = HIWORD(lParam);
SetWindowPos(ppi->pgi->hwndMC,
NULL, 0, 0, width, height,
SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
return(0);
}
case WM_NOTIFY:
switch (((NMHDR *)lParam)->code)
{
case MCN_SELCHANGE:
{
LPNMSELCHANGE pnms = (LPNMSELCHANGE)lParam;
ODS("MCN_SELCHANGE wDay=%d wMonth=%d yYear=%d to wDay=%d wMonth=%d yYear=%d",
pnms->stSelStart.wDay, pnms->stSelStart.wMonth, pnms->stSelStart.wYear,
pnms->stSelEnd.wDay, pnms->stSelEnd.wMonth, pnms->stSelEnd.wYear);
break;
}
case MCN_SELECT:
{
LPNMSELECT pnms = (LPNMSELECT)lParam;
ODS("MCN_SELECT wDay=%d wMonth=%d yYear=%d to wDay=%d wMonth=%d yYear=%d",
pnms->stSelStart.wDay, pnms->stSelStart.wMonth, pnms->stSelStart.wYear,
pnms->stSelEnd.wDay, pnms->stSelEnd.wMonth, pnms->stSelEnd.wYear);
break;
}
}
break;
default:
return(DefWindowProc(hwnd, uMessage, wParam, lParam));
}
}
VOID PASCAL CreateMonthCal(HWND hdlg, PPAGEINFO ppi)
{
WNDCLASS wc;
BOOL f;
DWORD dwStyle;
if (!GetClassInfo(g_hinst, szMonthCalWrapClass, &wc))
{
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)MCWrapWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(LPVOID);
wc.hInstance = g_hinst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szMonthCalWrapClass;
if (!RegisterClass(&wc))
{
ODS("Sample: ERROR - Can not register MCWrap class");
}
}
ppi->pgi->mcFlags = 0;
if (IsDlgButtonChecked(hdlg,IDC_DAYLIGHT)) ppi->pgi->mcFlags |= MCS_DAYSTATE;
if (IsDlgButtonChecked(hdlg,IDC_MULTISELECT)) ppi->pgi->mcFlags |= MCS_MULTISELECT;
if (IsDlgButtonChecked(hdlg,IDC_WEEKNUMBERS)) ppi->pgi->mcFlags |= MCS_WEEKNUMBERS;
if (IsDlgButtonChecked(hdlg,IDC_NOTODAY)) ppi->pgi->mcFlags |= MCS_NOTODAY;
ppi->pgi->dwSelRange = GetDlgItemInt(hdlg, IDC_MAXSELCOUNT, &f, FALSE);
dwStyle = WS_THICKFRAME|WS_VISIBLE|WS_POPUP|WS_CAPTION;
ppi->pgi->hwndMCWrap = CreateWindowEx(0, szMonthCalWrapClass, "MonthCal",
dwStyle,
ppi->pgi->rcMCWrap.left, ppi->pgi->rcMCWrap.top, 0, 0,
hdlg, NULL, g_hinst, (LPVOID)ppi);
if (ppi->pgi->hwndMCWrap)
{
RECT rcSize;
DWORD dwNumMonths;
// Size the MonthCal so it will fit the full month
MonthCal_GetMinReqRect(ppi->pgi->hwndMC, &rcSize);
AdjustWindowRect(&rcSize, dwStyle, FALSE);
SetWindowPos(ppi->pgi->hwndMCWrap, NULL,
0, 0, rcSize.right-rcSize.left, rcSize.bottom-rcSize.top,
SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
// Set maximum selection count (valid iff MCS_MULTISELECT)
MonthCal_SetMaxSelCount(ppi->pgi->hwndMC, ppi->pgi->dwSelRange);
// Update display of range of displayed months
dwNumMonths = MonthCal_GetMonthRange(ppi->pgi->hwndMC, GMR_VISIBLE, NULL);
SetDlgItemInt(hdlg, IDC_MONTHRANGE, dwNumMonths, FALSE);
}
else
{
ODS("Sample: ERROR - could not create MonthCal Wrap window");
}
}
void SetDlgItemHex(HWND hdlg, int id, UINT u)
{
char szText[80];
wsprintf(szText, "%X", u);
SetDlgItemText(hdlg, id, szText);
}
void DoHittest(PPAGEINFO ppi, HWND hdlg)
{
while (GetAsyncKeyState(VK_RBUTTON) >= 0) {
MCHITTESTINFO mchti;
MSG msg;
if (PeekMessage(&msg, NULL, 0,0, PM_REMOVE)) {
if (!IsDialogMessage(hdlg, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// try a hittest
GetCursorPos(&mchti.pt);
MapWindowPoints(HWND_DESKTOP, ppi->pgi->hwndMC, &mchti.pt, 1);
mchti.cbSize = sizeof(mchti);
SendMessage(ppi->pgi->hwndMC, MCM_HITTEST, 0, (LPARAM)&mchti);
SetDlgItemHex(hdlg, IDC_RETURN, mchti.uHit);
}
}
void DoSendMessage(PPAGEINFO ppi, HWND hdlg)
{
BOOL f;
LRESULT lres;
WPARAM wParam;
LPARAM lParam;
UINT uMsg = (UINT)GetDlgItemInt(hdlg, IDC_EDITMESSAGE, &f, FALSE);
if (uMsg < 100)
uMsg += MCM_FIRST;
wParam = (WPARAM)GetDlgItemInt(hdlg, IDC_EDITWPARAM, &f, FALSE);
lParam = (LPARAM)GetDlgItemInt(hdlg, IDC_EDITLPARAM, &f, FALSE);
lres = SendMessage(ppi->pgi->hwndMC, uMsg, wParam, lParam);
SetDlgItemHex(hdlg, IDC_RETURN, lres);
}
BOOL CALLBACK MonthCalDlgProc(HWND hdlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
PPAGEINFO ppi = (PPAGEINFO)GetWindowLong(hdlg, DWL_USER);
switch (uMessage)
{
case WM_INITDIALOG:
{
RECT rc;
ppi = (PPAGEINFO)lParam;
SetWindowLong(hdlg, DWL_USER, lParam);
SetDlgItemInt(hdlg, IDC_MAXSELCOUNT, 7, FALSE);
GetWindowRect(hdlg, &rc);
ppi->pgi->rcMCWrap.left = rc.left + 230;
ppi->pgi->rcMCWrap.top = rc.top + 41;
CheckDlgButton(hdlg, IDC_SHOWMC, BST_CHECKED);
CreateMonthCal(hdlg, ppi);
break;
}
case WM_COMMAND:
{
if (GET_WM_COMMAND_ID(wParam, lParam) == IDC_SHOWMC)
{
if (IsDlgButtonChecked(hdlg, IDC_SHOWMC))
{
if (ppi->pgi->hwndMC)
{
ODS("Sample: MonthCal already displayed!");
}
else
{
CreateMonthCal(hdlg, ppi);
}
}
else
{
if (ppi->pgi->hwndMC)
{
GetWindowRect(ppi->pgi->hwndMCWrap, &ppi->pgi->rcMCWrap);
DestroyWindow(ppi->pgi->hwndMCWrap);
ppi->pgi->hwndMCWrap = NULL;
}
else
{
ODS("Sample: MonthCal already destroyed!");
}
}
}
else if (ppi->pgi->hwndMC)
{
switch(GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_GETMONTHRANGE:
{
SYSTEMTIME rgst[2];
DWORD dwNumMonths;
dwNumMonths = MonthCal_GetMonthRange(ppi->pgi->hwndMC, GMR_VISIBLE, NULL);
SetDlgItemInt(hdlg, IDC_MONTHRANGE, dwNumMonths, FALSE);
MonthCal_GetMonthRange(ppi->pgi->hwndMC, GMR_DAYSTATE, rgst);
ODS("Sample: MCM_GMR DAYSTATE First Day=%d Month=%d Year=%d", rgst[0].wDay, rgst[0].wMonth, rgst[0].wYear);
ODS("Sample: MCM_GMR DAYSTATE Last Day=%d Month=%d Year=%d", rgst[1].wDay, rgst[1].wMonth, rgst[1].wYear);
break;
}
case IDC_MAXSELCOUNT:
if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
{
DWORD dwSelCount;
BOOL f;
dwSelCount = GetDlgItemInt(hdlg, IDC_MAXSELCOUNT, &f, FALSE);
MonthCal_SetMaxSelCount(ppi->pgi->hwndMC, dwSelCount);
}
break;
case IDC_HITTEST:
DoHittest(ppi, hdlg);
break;
case IDC_SENDMESSAGE:
DoSendMessage(ppi, hdlg);
break;
case IDC_SETCURSEL:
{
SYSTEMTIME st;
MonthCal_GetCurSel(ppi->pgi->hwndMC, &st);
st.wDay = st.wDay + 3;
if (st.wDay > 28)
{
st.wDay -= 27;
st.wMonth++;
if (st.wMonth == 13)
st.wMonth = 1;
}
MonthCal_SetCurSel(ppi->pgi->hwndMC, &st);
}
case IDC_MINDATE:
case IDC_MAXDATE:
{
DWORD dw=0;
static SYSTEMTIME st[2];
static BOOL fSet = FALSE;
if (IsDlgButtonChecked(hdlg,IDC_MINDATE)) dw |= GDTR_MIN;
if (IsDlgButtonChecked(hdlg,IDC_MAXDATE)) dw |= GDTR_MAX;
if (!fSet)
{
st[0].wDay = 4;
st[0].wMonth = 12;
st[0].wYear = 1969;
st[1].wDay = 4;
st[1].wMonth = 12;
st[1].wYear = 1999;
}
{
SYSTEMTIME stTmp[2];
DWORD dwTmp;
dwTmp = MonthCal_GetRange(ppi->pgi->hwndMC, &stTmp);
if (dwTmp & GDTR_MIN)
ODS("Sample: GDTR_MIN wDay=%d wMonth=%d wYear=%d", stTmp[0].wDay, stTmp[0].wMonth, stTmp[0].wYear);
if (dwTmp & GDTR_MAX)
ODS("Sample: GDTR_MAX wDay=%d wMonth=%d wYear=%d", stTmp[1].wDay, stTmp[1].wMonth, stTmp[1].wYear);
}
MonthCal_SetRange(ppi->pgi->hwndMC, dw, &st);
}
case IDC_DAYLIGHT:
case IDC_MULTISELECT:
case IDC_WEEKNUMBERS:
case IDC_NOTODAY:
{
DWORD dw;
dw = GetWindowLong(ppi->pgi->hwndMC, GWL_STYLE);
dw &= 0xFFFF0000;
if (IsDlgButtonChecked(hdlg,IDC_DAYLIGHT)) dw |= MCS_DAYSTATE;
if (IsDlgButtonChecked(hdlg,IDC_MULTISELECT)) dw |= MCS_MULTISELECT;
if (IsDlgButtonChecked(hdlg,IDC_WEEKNUMBERS)) dw |= MCS_WEEKNUMBERS;
if (IsDlgButtonChecked(hdlg,IDC_NOTODAY)) dw |= MCS_NOTODAY;
SetWindowLong(ppi->pgi->hwndMC, GWL_STYLE, dw);
break;
}
default:
break;
}
}
break;
}
case WM_NOTIFY:
switch (((NMHDR *)lParam)->code)
{
case PSN_KILLACTIVE:
if (ppi->pgi->hwndMCWrap)
ShowWindow(ppi->pgi->hwndMCWrap, SW_HIDE);
SetWindowLong(hdlg, DWL_MSGRESULT, 0);
break;
case PSN_SETACTIVE:
if (ppi->pgi->hwndMCWrap)
ShowWindow(ppi->pgi->hwndMCWrap, SW_SHOW);
SetWindowLong(hdlg, DWL_MSGRESULT, 0);
break;
case PSN_APPLY:
if (ppi->pgi->hwndMCWrap)
{
DestroyWindow(ppi->pgi->hwndMCWrap);
ppi->pgi->hwndMCWrap = NULL;
}
SetWindowLong(hdlg, DWL_MSGRESULT, 0);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}