
- •Int cbClsExtra;
- •Int cbWndExtra;
- •Создание и отображение окна
- •Int nWidth,
- •Int nHeight,
- •Оконная процедура
- •Int winapi MessageBox(
- •6) Дочернее окно может по своему дескриптору Chld получить дескриптор родительского окна при помощи функции:
- •8) При уничтожении родительского окна сообщение wm_destroy также рассылается всем дочерним окнам.
- •Параметры:
- •10) При уничтожении дочернего окна функцией DestroyWindow() родительскому окну тоже передается сообщение wm_destroy.
- •4) После того, как дочернее окно было создано, оно может посылать сообщение wm_command, уведомляющие pодительское окно об изменении своего состояния.
- •7) В программе функция InitStr() объявлена следующим образом:
- •Void InitStr(hwnd hWnd, char *s, int Max, char Sy);
- •Void InitStr(hwnd hWnd,char *s,int Max,char Sy)
- •11) Код функции обработки пароля приведён в листинге:
- •If(IsIconic(hwnd)) ShowWindow(hwnd,sw_restore);
- •If (!RegClass(WndProc,szMainClass,color_desktop))
11) Код функции обработки пароля приведён в листинге:
void OnChld(HWND hWnd,UINT message,int Length,LPARAM lParam)
{
if(strcmp(PassWord,TruePassWord)||Length)
MessageBox(hWnd, "Надо вспомнить правильный пароль","Скажи \"Пароль\"",0);
else MessageBox(hWnd, "Пароль принят","",0);
}
На основе сравнения строк и проверки длины введенного пароля функция принимает решение о приеме пароля и отображает соответствующее сообщение при помощи функции MessageBox().
12) При изменении размеров родительского окна в дочернее поступает сообщение WM_PAINT, по которому в переменной R формируются размеры родительского окна и при помощи функции MoveWindow(hWndC, R.left, R.bottom-iHeight, R.right, R.bottom-iHeight, 1) дочернему окну выделяется нижняя часть родительского окна.
15) Создание дочернего окна с дескриптором Chld оформлено отдельной функцией.
BOOL CreateChild(HWND hWnd)
{static WNDCLASS wc;
if(Chld) //Стандартный для WINDOWS прием - чтобы не думать, о
// действиях при попытке нового ввода до завершения предыдущего
DestroyWindow(Chld);
UnregisterClass("ReadStr",GetModuleHandle(NULL));
// Раз было окно, значит был и класс
// Если класс не убрать, получится ошибка при новой регистрации
}
wc.hInstance = GetModuleHandle(NULL);
wc.hbrBackground =(HBRUSH)(COLOR_BTNFACE+1);
wc.lpfnWndProc = ChldWndProc;
wc.lpszClassName = "ReadStr";
if (!RegisterClass(&wc)) return 0;
Chld=0;
Chld=CreateWindowEx (WS_EX_CLIENTEDGE, "ReadStr",
"Значения ", WS_CHILD|WS_VISIBLE, 30,30,60,60,
hWnd, HMENU(NumC),GetModuleHandle(NULL), NULL);
SetFocus(Chld);
return (int)Chld;
}
После первого щелчка в рабочей области родительского окна левой кнопкой мыши и до завершения ввода пароля дескриптор Chld не будет равен нулю. При повторном вызове функции CreateChild (то есть при повторной активизации левой кнопки мыши в клиентской области родительского окна) уничтожается дочернее окно и отменяется регистрация класса.
Пример №1: Создания главного окна с дочерним окном для ввода пароля.
#include "stdafx.h"
#include "resource.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
static TCHAR PassWord[7]; //введенный пользователем пароль
static TCHAR TruePassWord[]=_T("Password"); //Правильный пароль
static HWND Chld;
static WORD i;
static TCHAR *Str=NULL;
static int sMax;
int wHeight=30; //Высота дочернего окна
static TCHAR Sym[80];
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CreateChild(HWND hWnd);
void InitStr(HWND hWnd,TCHAR *s,int Max,TCHAR Sy);
void OnChld(HWND hWnd,UINT message,int Length,LPARAM lParam);
LRESULT APIENTRY ChldWndProc (HWND UkOkn,UINT message, WPARAM wParam,LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_CHILD_WINDOW, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_CHILD_WINDOW);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT APIENTRY ChldWndProc(HWND hWndC,UINT message,WPARAM wParam,LPARAM lParam)
{ RECT R;
switch (message)
{
case WM_CHAR:
if (LOWORD(wParam)==VK_RETURN || i>=20)
{
Str[i]=0;
PostMessage(GetParent(hWndC),WM_COMMAND,MAKELONG(NumC, i-sMax),0);
i=0;
DestroyWindow(hWndC);
UnregisterClass(_T("ReadStr"),GetModuleHandle(NULL));
}
else
{
if(++i<=sMax)
Str[i-1]=(char )LOWORD(wParam);
InvalidateRect(hWndC,NULL,1);
}
break;
case WM_PAINT:
{PAINTSTRUCT ps;
GetClientRect(GetParent(hWndC),&R);
MoveWindow(hWndC,R.left,R.top,R.right,R.top+wHeight,1);
BeginPaint(hWndC,&ps);
SetBkMode(ps.hdc, TRANSPARENT);
TextOut(ps.hdc,0,0,_T("Введите пароль: "),14);
TextOut(ps.hdc,17*8,0,Sym,i);
EndPaint(hWndC,&ps);
}
return 0;
default:
return DefWindowProc(hWndC,message,wParam,lParam);
}
return 0;
}
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_CHILD_WINDOW);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCWSTR)IDC_CHILD_WINDOW;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
400, 300, 500, 500, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
void OnChld(HWND hWnd,UINT message,int Length,LPARAM lParam)
{
if(_tcscmp(PassWord,TruePassWord)||Length)
MessageBox(hWnd, _T("Надо вспомнить правильный пароль"),_T("Скажи \"Пароль\""),0);
else MessageBox(hWnd, _T(" Пароль принят"),_T(""),0);
}
BOOL CreateChild(HWND hWnd)
{static WNDCLASS wc;
if(Chld) //Стандартный для WINDOWS прием - чтобы не думать, о действих при
{ //попытке нового ввода до завершения
DestroyWindow(Chld); // предыдущего.
UnregisterClass(_T("ReadStr"),GetModuleHandle(NULL));
// Раз было окно, значит,был и класс
// Если класс не убрать, получится ошибка при новой регистрации
}
wc.hInstance = GetModuleHandle(NULL);
wc.hbrBackground =(HBRUSH)(COLOR_BTNFACE+1);
wc.lpfnWndProc = ChldWndProc;
wc.lpszClassName = _T("ReadStr");
if (!RegisterClass(&wc)) return 0;
Chld=0;
Chld=CreateWindowEx
( WS_EX_CLIENTEDGE, _T("ReadStr"), _T(" Значения "),
WS_CHILD|WS_VISIBLE ,
30,30,60,60,
hWnd, HMENU(NumC),GetModuleHandle(NULL), NULL);
SetFocus(Chld);
return (int)Chld;
}
void InitStr(HWND hWnd,TCHAR *s,int Max,TCHAR Sy)
{
Str=s;
sMax=Max;
int j;
for (j=0; j<21;j++)Sym[j]=Sy;
Sym[j]=0;
CreateChild(hWnd);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case NumC:
OnChld(hWnd,message,HIWORD(wParam),lParam); // Обработка пароля
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_LBUTTONDOWN:
InitStr(hWnd,PassWord,8,_T('*'));
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Пример 2: Окно приложения стиля временного окна с кнопкой минимизации и с фоном цвета рабочего стола Windows занимает весь экран. При попытке запустить второй экземпляр приложения на передний план перемещается окно первого экземпляра и завершается работа.
Шаг 1)
Для поиска приложения используется функция FindWindow:
HWND hwnd= FindWindow(szMainClass,szTitle);
Данная функция возвращает дескриптор окна класса szMainClass с заголовком szTitle. Если такого окна нет, то это первый экземпляр приложения и дескриптору hwnd присваивается NULL. Иначе возвращается дескриптор найденного окна.
Если работает экземпляр другого приложения с окном класса с таким же именем szMainClass и заголовком szTitle, то данная функция вернёт дескриптор окна другого приложения иначе переходим к шагу 5.
Шаг 2)
Если «предыдущий экземпляр приложения» обнаружен, то выводим сообщение:
MessageBox(hwnd,”Можно запускать только одну копию приложения!!!\n\n”
“Перемещаю на передний план первый экземпляр”,
szTitle,MB_OK);
Шаг 3)
До перемещения окна на передний план необходимо проверить состояние этого окна и, если оно свёрнуто, то восстанавливаем его предыдущее состояние: