Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.10.2013, 13:18   #1
Грендайзер
Пользователь
 
Регистрация: 15.10.2013
Сообщений: 29
По умолчанию Кнопки в WinApi

Доброго времени суток, господа программисты Есть такая вот проблемка, а точнее недопонимание. Сам я инженер, и от программирования под Windows далёк, но вот тут пришлось сделать програмку для управления устройством по COM порту (точнее по USB но через адаптер). И как оказалось, можно конечно было графическим редактором воспользоваться, но когда я взялся выяснять, как всё это делается, я об этом не знал, так что навалился на WinApi... нууу и затянуло Так вот, программа состоит из родит. окна и из двух кнопок. Внимание вопрос номер адын: хочу, что б при нажатии на кнопку надпись на ней менялась. В принципе при нажатии на одну из кнопок (bt1) надпись на ней меняется, но по почему, она становится прежней если я нажимаю на другую кнопку? Есть ещё вопросы но я их тогда следом задам. Заранее спасибо. Исходничек прилагается. Почти всё что связано с работой с портом я выкинул, что бы не отвлекало.
Вложения
Тип файла: rar Hello1.rar (1.7 Кб, 75 просмотров)

Последний раз редактировалось Грендайзер; 16.10.2013 в 13:22.
Грендайзер вне форума Ответить с цитированием
Старый 16.10.2013, 22:50   #2
satmasterz
Новичок
Джуниор
 
Регистрация: 16.10.2013
Сообщений: 1
По умолчанию

Отличное решение!
---------------
http://fitoterapevt.pp.ua/likarski-r...ivosti-recepti
satmasterz вне форума Ответить с цитированием
Старый 17.10.2013, 04:42   #3
Vladiger
Пользователь
 
Регистрация: 31.08.2013
Сообщений: 93
По умолчанию

Цитата:
Сообщение от Грендайзер Посмотреть сообщение
хочу, что б при нажатии на кнопку надпись на ней менялась.
SetWindowText(hBtn1, "Закрыть порт");

Цитата:
Сообщение от Грендайзер Посмотреть сообщение
В принципе при нажатии на одну из кнопок (bt1) надпись на ней меняется, но по почему, она становится прежней если я нажимаю на другую кнопку?
У Вас ошибка в обработчике собития по нажатию кнопки bt1. Вот в этом месте:
Код:
case ID_BUTTON:
	btn1 = CreateWindow("BUTTON", "закрыть порт", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 70, 45, 240, 20, hMainWnd, (HMENU)ID_BUTTON, NULL, NULL);
	return 0;
Вы не меняете текст на кнопке, вы создаете новую кнопку, но при этом экземпляр старой кнопки btn1 остается где то в воздухе, потому что он не был удален. Получается не очень хорошая штука.
Перед созданием новой кнопки, старую нужно удалять, например так:
Код:
case ID_BUTTON:
	DestroyWindow(btn1);
	btn1 = CreateWindow("BUTTON", "закрыть порт", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 70, 45, 240, 20, hMainWnd, (HMENU)ID_BUTTON, NULL, NULL);
	return 0;
Но в Вашем же случае, я вообще не вижу смысла создавать новую кнопку, если Вам требуется всего навсего просто изменить её текст:
Код:
case ID_BUTTON:
	SetWindowText(btn1, "Закрыть порт");
	return 0;
Исправленный вариант:
Код:
#include <windows.h>
//#include "stdafx.h"

#define ID_BUTTON_1 3000
#define ID_BUTTON_2 3001

HWND hBtn1;
HWND hBtn2;
HANDLE hCOM; // хендл сом порта
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {

	HWND hMainWnd; // хендл будущего окна
	char szClassName[] = "MyClass";
	MSG msg;
	WNDCLASSEX wc;

	// Заполняем структуру класса окна
	wc.cbSize = sizeof(wc);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc; //WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = "MyClass";
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

	// Регистрируем класс окна
	if (!RegisterClassEx(&wc)) {
		MessageBox(NULL, "Cannot register class", "Error", MB_OK);
		return 0;
	}

	// Создаем основное окно приложения
	hMainWnd = CreateWindow(szClassName, "WndProc", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
	if (!hMainWnd) {
		MessageBox(NULL, "Cannot create main window", "Error", MB_OK);
		return 0;
	}

	//Создаем кнопки hBtn1 и hBtn2;
	hBtn1 = CreateWindow("BUTTON", "Открыть порт", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 70, 45, 240, 20, hMainWnd, (HMENU)ID_BUTTON_1, hInstance, NULL);
	hBtn2 = CreateWindow("BUTTON", "Generate key2", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 400, 200, 250, 250, hMainWnd, (HMENU)ID_BUTTON_2, hInstance, NULL);


	// Показываем окно
	ShowWindow(hMainWnd, nCmdShow);
	UpdateWindow(hMainWnd);

	// Выполняем цикл обработки сообщений до закрытия приложения
	while(GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hMainWnd, UINT msg, WPARAM wParam, LPARAM lParam) {

	char buffer = '1';
	//int fl;
	//DWORD signal;
	//DWORD dwByteWrite;

	//HWND hBtn1;
	HDC hDC;
	PAINTSTRUCT ps;
	RECT rect;

	switch (msg) {
		case WM_PAINT:
			hDC = BeginPaint(hMainWnd, &ps);

			GetClientRect(hMainWnd, &rect);
			DrawText(hDC, "Hello, World!", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

			EndPaint(hMainWnd, &ps);
			return 0;

		case WM_CLOSE:
			DestroyWindow(hMainWnd);
			return 0;

		case WM_DESTROY:
			PostQuitMessage(0);
			return 0;


		case WM_COMMAND:
			switch(wParam) {
				case ID_BUTTON_1:
					SetWindowText(hBtn1, "Закрыть порт");
					return 0;
				
				case ID_BUTTON_2:
					//WriteFile(
					// hCOM, Для работы с портом!!!
					// &buffer,
					// sizeof(buffer),
					// &dwByteWrite,
					// &overlapTX
					// );

					//signal = WaitForSingleObject(overlapTX.hEvent, INFINITE);
					//fl = ((signal == WAIT_OBJECT_0) && (GetOverlappedResult(hCOM, &overlapTX, &dwByteWrite, true))) ? true : false;
					//CloseHandle(hCOM);

					return 0;
			}

		case WM_KEYDOWN:
			switch(wParam) {
				case VK_ESCAPE:
					SendMessage(hMainWnd, WM_CLOSE, 0, 0);
					break;
			}
			break;
		
		default:
			return DefWindowProc(hMainWnd, msg, wParam, lParam);
	}
	return 0;
}

Последний раз редактировалось Vladiger; 17.10.2013 в 08:24.
Vladiger вне форума Ответить с цитированием
Старый 17.10.2013, 10:20   #4
Грендайзер
Пользователь
 
Регистрация: 15.10.2013
Сообщений: 29
По умолчанию

Ух ты! Большое спасибо! У меня ещё была пара вопросиков, но сначала это дело обмозгую!
Грендайзер вне форума Ответить с цитированием
Старый 17.10.2013, 11:10   #5
Vladiger
Пользователь
 
Регистрация: 31.08.2013
Сообщений: 93
По умолчанию

Кстати, забыл написать: - Раз уж упомянул про DestroyWindow(HWND hWnd), то должен заметить, что это касается всех окон/контролов созданных функцией CreateWindow(), в том числе и основного окна приложения...
Не знаю что страшного может произойти если перед выходом из программы основное окно не удалить, возможны утечки памяти, но точно не знаю, не задавался пока таким вопросом. И тем не менее, удалять его нужно.
Перед выходом из программы, нужно добавить строчку DestroyWindow(hMainWnd);

То есть примерно так:
Код:
while(GetMessage(&msg, NULL, 0, 0)) {
	TranslateMessage(&msg);
	DispatchMessage(&msg);
}
DestroyWindow(hMainWnd); // Уничтожаем основное окно
UnregisterClass(szClassName, NULL); // Освобождаем память, отменяя регистрацию класса основного окна.
return msg.wParam;

Последний раз редактировалось Vladiger; 17.10.2013 в 11:18.
Vladiger вне форума Ответить с цитированием
Старый 17.10.2013, 11:25   #6
Грендайзер
Пользователь
 
Регистрация: 15.10.2013
Сообщений: 29
По умолчанию

Vladiger, большое спасибо, на данный момент, все вопросы с которыми я столкнулся Вы помогли разрешить.
Грендайзер вне форума Ответить с цитированием
Старый 17.10.2013, 11:28   #7
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,331
По умолчанию

При завершении процесса освобождаются все его ресурсы, включая и окна.
Удалять WS_CHILD окна необязательно - они автоматически закрываются при закрытии родителя.
waleri вне форума Ответить с цитированием
Старый 17.10.2013, 11:51   #8
Vladiger
Пользователь
 
Регистрация: 31.08.2013
Сообщений: 93
По умолчанию

А вообще то пардон, не заметил вот это:
Код:
case WM_CLOSE:
	DestroyWindow(hMainWnd);
	return 0;
То есть основное окно в Вашем варианте разрушается по сообщению WM_CLOSE - этого достаточно. Как выше было добавлено waleri, кнопки созданы дочерними окнами WS_CHILD, а значит удалятся автоматически вместе с основным окном.
Единственное что сюда можно было добавить, это отмену регистрации класса, например так:
Код:
case WM_CLOSE:
	DestroyWindow(hMainWnd);
	UnregisterClass(szClassName, NULL);
	return 0;
Но переменная szClassName является локальной в функции WinMain и в обработчике WndProc она недоступна. Вариантов 2, либо сделать её глобальной, либо отмену регистрации делать не в обработчике, а непосредственно перед выходом из программы (как и было замечено выше)...
Это конечно не суть важно где делать эти отмены и уничтожения окон, главное что бы вы суть уловили. Зарегистрировали класс, создали окно - значит перед выходом нужно все это дело освободить!
Vladiger вне форума Ответить с цитированием
Старый 17.10.2013, 12:12   #9
Грендайзер
Пользователь
 
Регистрация: 15.10.2013
Сообщений: 29
По умолчанию

Опаньки... т.е. ещё и класс надо разрегистрировать? А вот об этом я даже и не знал...
Грендайзер вне форума Ответить с цитированием
Старый 17.10.2013, 12:22   #10
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,331
По умолчанию

WM_CLOSE стандартно сам закроет окно в DefWindowProc.
Отрегистрировать окно в обработчике WM_CLOSE не получится, потому что окно в этот момент все еще существует, т.е. класс окна используется.

При выходе из программы *все* ресурсы освобождаются.
waleri вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Различие кода mfc и WinApi(mfc ручками набили, а WinApi автоматически с генерировался!! нужно явное отличие, не могу найти) Артём1991 Помощь студентам 0 25.03.2012 17:13
Цвет кнопки,Delphi WinApi red-eye Win Api 0 08.01.2012 21:49
Изменение свойств кнопки через WinAPI Никки Win Api 12 20.09.2009 15:01
UCOZ: Кнопки кнопки на изображении ReDuX HTML и CSS 19 25.04.2008 02:39
триггерные кнопки и кнопки переключатели в DELPHI MARGO Помощь студентам 3 12.11.2007 17:35