Стандартный календарь в Windows

  • Автор темы mike2007
  • Дата начала
M

mike2007

#1
Здравствуйте.
Как настроить функцию обратного вызова?
Сделал стандартно вот так:
Код:
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR	 lpCmdLine,
int	  nCmdShow)
{
BOOL bRet;
MSG msg;
HWND hwndMain; 

MyRegisterClass(hInstance);

hwndMain = CreateWindowEx( 
0,					 // no extended styles		  
MONTHCAL_CLASS,		  // class name				  
"Main Window",		 // window name				 
WS_OVERLAPPEDWINDOW	// vertical scroll bar		 
100,		 // default horizontal position 
100,		 // default vertical position	
200,		 // default width				
200,		 // default height			  
(HWND) NULL,			// no parent or owner window	
(HMENU) NULL,		  // class menu used			 
hInstance,			 // instance handle			 
NULL);				 // no window creation data	 

if (!hwndMain) 
return FALSE; 


ShowWindow(hwndMain, SW_SHOWDEFAULT); 
UpdateWindow(hwndMain);


while( (bRet = GetMessage( &msg, hwndMain, 0, 0 )) != 0)
{ 
if (bRet == -1)
{
DestroyWindow(hwndMain);
}
else
{
TranslateMessage(&msg); 
DispatchMessage(&msg); 
}
}
return msg.wParam;

}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX); 

wcex.style			= CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc	= (WNDPROC)WndProc;
wcex.cbClsExtra		= 0;
wcex.cbWndExtra		= 0;
wcex.hInstance		= hInstance;
wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_MAIN2);
wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName	= (LPCSTR)IDC_MAIN2;
wcex.lpszClassName	= szWindowClass;
wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

return RegisterClassEx(&wcex);

}
А в эту функцию обратного вызова программа не попадает:
Код:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

switch (message) 
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;

}
Изменил строку код C++
Код:
wcex.lpszClassName	= szWindowClass;
в функции MyRegisterClass(HINSTANCE hInstance)
на строкукод C++
Код:
wcex.lpszClassName	= MONTHCAL_CLASS;
и функцию обратного вызова заработала, но вместо календаря появляется белый фон.
Что надо сделать что бы появился календарь?
Подскажите пожалуйста.
 
V

Vladimirpb

#2
Начнём с того, что функция, которую вы называете функцией обратного вызова на самом деле всегда и везде называется оконной процедурой.
См. MSDN, описание структуры WNDCLASSEX
...
lpfnWndProc
Pointer to the window procedure. You must use the CallWindowProc function to call the window procedure. For more information, see WindowProc.
...

Далее, приведённый вами код даже не будет компилироваться из-за ошибок.
Для обычного окна весь код выглядит так:

файл WinMain.h:

Код:
#include <windows.h>
#include <shlwapi.h>
#include <COMMCTRL.H>
//***************************************************************************
ATOM MyRegisterClass(HINSTANCE hInstance, const char *szWindowClass);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
//***************************************************************************

файл WinMain.cpp:

#include "WinMain.h"
//***************************************************************************
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR	 lpCmdLine,
int	  nCmdShow)
{
BOOL bRet;
MSG msg;
HWND hWndMain;
const char *szWindowClass = "MyWindow";

MyRegisterClass(hInstance, szWindowClass);

hWndMain = CreateWindowEx(
0,					 // no extended styles		 
szWindowClass,		  // class name				 
"Main Window",		 // window name				 
WS_OVERLAPPEDWINDOW,	// vertical scroll bar		 
100,		 // default horizontal position 
100,		 // default vertical position	
200,		 // default width				
200,		 // default height			 
(HWND) NULL,			// no parent or owner window	
(HMENU) NULL,		  // class menu used			 
hInstance,			 // instance handle			 
NULL);				 // no window creation data	 

if (!hWndMain)
return FALSE;


ShowWindow(hWndMain, SW_SHOW);
UpdateWindow(hWndMain);


while ((bRet = GetMessage(&msg, NULL, 0, 0 )))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;

}
//***************************************************************************
ATOM MyRegisterClass(HINSTANCE hInstance, const char *szWindowClass)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style		 = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc	= (WNDPROC)WndProc;
wcex.cbClsExtra	 = 0;
wcex.cbWndExtra	 = 0;
wcex.hInstance	 = hInstance;
wcex.hIcon		 = NULL; //LoadIcon(hInstance, (LPCTSTR)IDI_MAIN2);
wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName  = NULL;//(LPCSTR)IDC_MAIN2;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm		= NULL; //LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

return RegisterClassEx(&wcex);

}
//***************************************************************************
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];

switch (message)
{
case WM_CLOSE:
DestroyWindow(hWnd);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
//***************************************************************************

Для окна с календарём весь код выглядит так:

файл WinMain.h:

#include <windows.h>
#include <shlwapi.h>
#include <COMMCTRL.H>
//***************************************************************************

файл WinMain.cpp:

#include "WinMain.h"
//***************************************************************************
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR	 lpCmdLine,
int	  nCmdShow)
{
BOOL bRet;
MSG msg;
HWND hWndMain;
const char *szWindowClass = "MyWindow";

INITCOMMONCONTROLSEX stINITCOMMONCONTROLSEX;
memset(&stINITCOMMONCONTROLSEX, 0, sizeof(INITCOMMONCONTROLSEX));
stINITCOMMONCONTROLSEX.dwSize = sizeof(INITCOMMONCONTROLSEX);
stINITCOMMONCONTROLSEX.dwICC = ICC_WIN95_CLASSES;
stINITCOMMONCONTROLSEX.dwICC = ICC_DATE_CLASSES;
bRet = InitCommonControlsEx(&stINITCOMMONCONTROLSEX);

hWndMain = CreateWindowEx(
0,					 // no extended styles		 
MONTHCAL_CLASS,
"Main Window",		 // window name				 
WS_OVERLAPPEDWINDOW,	// vertical scroll bar		 
100,		 // default horizontal position 
100,		 // default vertical position	
200,		 // default width				
200,		 // default height			 
(HWND) NULL,			// no parent or owner window	
(HMENU) NULL,		  // class menu used			 
hInstance,			 // instance handle			 
NULL);				 // no window creation data	 

if (!hWndMain)
return FALSE;


ShowWindow(hWndMain, SW_SHOW);
UpdateWindow(hWndMain);


while ((bRet = GetMessage(&msg, hWndMain, 0, 0 )) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;

}
//***************************************************************************
В установках проекта на вкладке Link необходимо подключть библиотеку Comctl32.lib.

Обратите особое внимание на изменение условия выхода из цикла обработки сообщения, отсутствие ф-ии регистрации класса окна и
инициализацию системных элементов управления,

см. MSDN
...
Common Controls

The common controls are a set of windows that are implemented by the common control library, which is a dynamic-link library (DLL) included with the Microsoft® Windows® operating system. Like other control windows, a common control is a child window that an application uses in conjunction with another window to perform I/O tasks.

....


Обратите особое внимание на значительное упрощение кода.

Читайте Ч.Петзолд "Программирование для Windows 95"
 
M

mike2007

#3
Я и так делал, но тогда где можно зарегистрировать оконную процедуру для окна с календарем, ведь мне нужно отлавливать события совершаемые с календарем. И вообще можно это сделать или нет?