Регистрация Главная Пользователи Все разделы прочитаны
Сообщения за день Справка Регистрация
Навигация
Zhyk.org LIVE! Реклама на Zhyk.org Правила Форума Награды и достижения Доска "почета"

Ответ
 
Опции темы
Старый 23.01.2009, 04:57   #1
Заблокирован
 Капитан
Аватар для Ivan_32
 
Ivan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компанииIvan_32 душа компании
Регистрация: 14.05.2008
Сообщений: 253
Популярность: 1015
Сказал(а) спасибо: 666
Поблагодарили 451 раз(а) в 173 сообщениях
Отправить сообщение для Ivan_32 с помощью ICQ Отправить сообщение для Ivan_32 с помощью Telegram Отправить сообщение для Ivan_32 с помощью Skype™
 
По умолчанию Добавляем к окну элементы управления.

Немного теории
У окон в Win32 есть несколько классов, каждый из них имеет свои сообщения, нотификации и конечно же внешний вид. Сегодня мы познакомимся с некоторыми распространенными видами оконных классов, вернее говоря с базовыми и напишем на их основе простенькую программу использующую контролы. Ну что ж приступим.

Открываем нашу заготовку, сделанную в предыдущем уроке и начинаем ваять. Освежим память. Заготовка выглядит вот так:
Код:

#include "stdafx.h"
#include <windows.h>
LRESULT WINAPI mainProc(HWND hWnd,UINT message,WPARAM wp,LPARAM lp);
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    MSG msg;
     HWND hMain=CreateWindowEx(0,WC_DIALOG,"Hello world",WS_VISIBLE|WS_SYSMENU,CW_USEDEFAULT,CW_USEDEFAULT,200,200,0,0,0,0);
    SetWindowLong(hMain,DWL_DLGPROC,(long)mainProc);//Примечание 1.
    SendMessageA(hMain,WM_CREATE,0,0);
    while(GetMessage(&msg,0,0,0)!=NULL)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}
LRESULT WINAPI mainProc(HWND hWnd,UINT message,WPARAM wp,LPARAM lp)
{
    switch(message)
    {
    case WM_CREATE:
		{
		
		}break;
    case WM_CLOSE:
        {
        PostQuitMessage(0);    
        }break;
    }
    return 0;
}
Этот код немного отличается от того который мы писали в прошлый раз. Отличие состоит лишь в том что тут функция mainProc сначала объявлена, а потом уже инициализирована. Stdafx.h это дефолтовый файл-заголовок для проекта, там прописана директива WIN32_LEAN_AND_MEAN и не более.
Примечание 1: Эта строка посылает сообщение нашему окну, оно обрабатывается функцией mainProc как и другие сообщения.

Думаю тут все понятно. Как я уже говорил любой элемент управления это по сути окно, которому дали предка(parent), сами по себе они тоже могут жить, если не указать в функции CreateWindowEx окно-предок.

Вот код который добавит к нашей форме кнопку:
Код:
CreateWindowEx(0,"button","Press Me",WS_VISIBLE|WS_CHILD,50,73,100,20,hWnd,(HMENU)1000,0,0);
WS_CHILD - это стиль дочернего окна, без него наша кнопка появится в отдельном окне и ее события не будут обрабатываться функцией mainProc.
Эту строку следует поместить в событие WM_CREATE, можно конечно создавать кнопки еще на начальном этапе в функции WinMain, тогда вместо hWnd стоит поставить имя дескриптора окна(в нашем случае hMain).
1000 это уникальный идентификатор нашего окна(контрола).

Наша кнопка уже отображается и на нее даже можно нажать, но почему то ничего не происходит. Это так потому что мы не добавили обработчик событий для нашей кнопки. За обработку ВСЕХ сообщений контролов отвечает сообщение WM_COMMAND но к нему поступают сообщения для всех контролов, но каждое сообщение в WPARAM содержит идентификатор контрола о котором говорилось выше. Видоизменим наш код, так что бы при нажатии на нашу кнопку выскакивал MessageBox:
Код:

case WM_COMMAND:
{
  if(wp==1000)
  {
    MessageBox(0,"You pressd me, thank you!","Press Me message",0);
  }
}break;
Этот обработчик нужно добавить в функцию mainProc.

Ну что ж теперь наша кнопка реагирует на нажатие. Теперь поставим себе задачу написать программу которая будет копировать текст из первого текстового поля во второе. Это наименее сложный пример использования контролов. Класс контрола текстовго поля называется "edit".

Функция которая вытащит текст из этого текствого поля:
Код:
int GetWindowText(      
    HWND hWnd,
    LPTSTR lpString,
    int nMaxCount
);
1. Дескриптор(хендл - HWND) окна.
2. Адрес строки приемника.
3. Максимальное количество получаемых символов.
Функция возвращает количество полученных символов.

Функция которая установит второму текстовому полю текст из первого поля:
Код:
BOOL SetWindowText(      
    HWND hWnd,
    LPCTSTR lpString
);
1. Дескриптор окна приемника.
2. Адрес строки для установки.
Функция возвращает TRUE (1) если операция прошла успешно.

Так же нам понадобится выделить память-буффер для строки. Сделаем мы это с помощью вот такой нехитрой строки:
Код:
char* szBuffer=(char*)malloc(260);
Функция malloc - дефолтовая функция в С++ для выделения памяти, для работы с ней надо подключить файл stdlib.h.

Итак вроде бы все готов для написания нашей незамысловатой программы. Продолжение в следущем посте.



Практическая часть
Теперь мы пошагово напишем и разберем код нашей программы, но сначала сформируем тех.задание.

Требования к программе:
1. Программа должна копировать строку из одного контрола в другой.
2. Корректно работать и иметь переносимый функционал.

Первое требование мы реализуем без проблем, а вот что же понимается под вторым? А понимается под ним то что мы напишем функцию которая будет уметь копировать текст из одного контрола во второй. Функция будет полностью переносимой, т.е. не будет использовать переменные нашей программы, все данные будут передаваться через аргументы.

Алгоритм работы нашей функции:
1. В аргументы передаются такие параметры:
1.Адрес текстового буфера.
2.Дескриптор первого окна.
3.Дескриптор второго окна.
2. С помощью функции GetWindowText, текст из первого контрола будет перенесен в текстовый буфер(адрес которого передается в функцию первым параметром)
3. С помощью функции SetWindowText, текст второго окна будет установлен как текст содержащийся в текстовом буфере.
Функция будет иметь тип возвращаемого значение BOOL , в случае удачного завершения функция возвратит результат TRUE.

Код функции CopyText :
Код:
bool CopyText(char* szBf,HWND hEdit0,HWND hEdit1)
{
	bool res=FALSE;
	if(GetWindowTextA(hEdit0,szBf,260)!=NULL)
	{
		if(SetWindowTextA(hEdit1,szBf)!=NULL)
		{
			res=TRUE;
		}
	}
	return res;
}
Как видно все предельно просто.

Теперь напишем графическую оболочку.
Для начала нужно определится с подключаемыми файлами и константами. Ими станут windows.h и stdio.h. Так же очень неплохо будет сделать макросы (препроцессорной директивой #define) для идентификаторов наших контролов. Контролов у нас всего 3, значит и идентификаторов тоже будет три : 1000(Кнопка) 1001(текстовое поле 1) 1002(текстовое поле 2). Так же нам понадобятся 3 дескриптора окна для наших контролов. С учетом всех приведенных требований можно написать такой код:
Код:
#include <windows.h>
#include <stdlib.h>
#define button 1000
#define edit1 1001
#define edit2 1002
static HWND hBt;
static HWND hEditA;
static HWND hEditB;
Далее нужно указать прототипы наших функций:
Код:
bool CopyText(char* szBf,HWND hEdit0,HWND hEdit1);
LRESULT WINAPI mainProc(HWND hWnd,UINT message,WPARAM wp,LPARAM lp);
Функция WinMain выглядит вот так:
Код:
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	MSG msg;
 	HWND hMain=CreateWindowEx(0,WC_DIALOG,"Hello world",WS_VISIBLE|WS_SYSMENU,CW_USEDEFAULT,CW_USEDEFAULT,200,200,0,0,0,0);
	SetWindowLong(hMain,DWL_DLGPROC,(long)mainProc);
	SendMessageA(hMain,WM_CREATE,0,0);
	while(GetMessage(&msg,0,0,0)!=NULL)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}
Никаких изменений по сравнению с предыдущим примером.
Выделять память для строки мы будем в начале функции mainProc, до начала обработки сообщений. С учетом этих изменений функция mainProc будет выглядеть вот так:
Код:
LRESULT WINAPI mainProc(HWND hWnd,UINT message,WPARAM wp,LPARAM lp)
{
        Примечание 0:
	char* szTextBuffer=(char*)malloc(260);
	switch(message)
	{
	case WM_CREATE:
		{
//Примечание 1:			hEditA=CreateWindowEx(0,"edit",0,WS_VISIBLE|WS_CHILD|WS_BORDER,10,10,100,20,hWnd,(HMENU)edit1,0,0);
			hEditB=CreateWindowEx(0,"edit",0,WS_VISIBLE|WS_CHILD|WS_BORDER,10,35,100,20,hWnd,(HMENU)edit2,0,0);
			hBt=CreateWindowEx(0,"button","Press Me",WS_VISIBLE|WS_CHILD,10,65,100,20,hWnd,(HMENU)button,0,0);
		}break;
	case WM_COMMAND:
		{
                        //Примечание 2:
			if(wp==button)
			{
			CopyText(szTextBuffer,hEditA,hEditB);
			}
                        //Конец второго примечания.
		}break;
	case WM_CLOSE:
		{
		PostQuitMessage(0);	
		}break;
	}
	return 0;
}
Примечание 0: То самое выделение памяти, 260 байт должно вполне хватить.
Примечание 1: WS_BORDER - стиль рамки вокруг контрола. Для текстовго поля это черное обрамление подчеркивающее его границы. Третий параметр с конца это идентификатор окна. Второй параметр это имя класса контрола.
Примечание 2: Если в wp находится идентификатор кнопки то выполнится наша функция.

Вот собственно и все. В заключение приведу весь код нашей программы:
Развернуть код

To Be Continued...


Последний раз редактировалось Ivan_32; 25.01.2009 в 11:24. Причина: Добавлено сообщение
  Ответить с цитированием
Ответ

Метки
c++, окну, управления, winapi, элементы, добавляем

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Заявление об ответственности / Список мошенников

Часовой пояс GMT +4, время: 04:47.

Пишите нам: [email protected]
Copyright © 2024 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net