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

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

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

Восстановить пароль

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

Ответ
 
Опции темы Поиск в этой теме
Старый 04.01.2023, 19:19   #1
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию Панель инструментов.

Здравствуйте! Начал разбираться с диалоговыми панелями, но процесс идёт не совсем так, как мне бы того хотелось, дело в том, что диалоговые панели предлагается создавать в памяти, это не плохо, но малопонятно. Хотелось бы вникнуть, но, видимо, без посторонней помощи никак(
Почему используется функция LocalAlloc() для выделения памяти, а не, скажем, malloc()?
Как подбирается значения для выделения памяти LocalAlloc(LPTR, 500|1000|2000) т.е. не наугад же, зачем выделять слишком много памяти или наоборот слишком мало, как рассчитать точное количество памяти и возможно ли это?
В книге говорится в выравнивании на границу слова и вообще используются типы строк char, которые преобразуются к строкам UNICODE, возможно, сейчас что-то поменялось в этом плане, возможно, нужно сразу задавать-пользоваться широкие символы?


Это вспомогательные функции, которые автор создал для примера.
Код:
#ifndef CREATEDLG_H
#define CREATEDLG_H

#include<windows.h>
#include<tchar.h>
LPWORD lpwAlign(LPWORD lpln);
int nCopyAnsiToWideChar(LPWORD lpWCStr, LPCSTR lpAnsi);
void DlgTemplate(PWORD& p, DWORD lStyle, int Items,
	int x, int y, int cx, int cy, LPSTR txt);
void DlgItemTemplate(PWORD& p, DWORD lStyle, int x, int y, int cx, 
	                 int cy, WORD id, LPSTR classname, LPSTR txt);

LPWORD lpwAlign(LPWORD lpln)
{
	ULONG ul = (ULONG)lpln;
	ul += 3;
	ul >>= 2;
	ul <<= 2;
	return (LPWORD)ul;
}

//Здесь меня смущает параметр lpWCStr точнее его тип, как функция скопирует туда (в LPWORD)
//преобразованные символы
int nCopyAnsiToWideChar(LPWORD lpWCStr, LPCTSTR lpAnsi)
{
	int cchAnsi = lstrlen(lpAnsi);
	return MultiByteToWideChar(	GetACP(), MB_PRECOMPOSED, lpAnsi, cchAnsi,
		lpWCStr, cchAnsi) + 1;
}

void DlgTemplate(PWORD& p, DWORD lStyle, int Items,
	int x, int y, int cx, int cy, LPCTSTR txt)
{
	*p++ = LOWORD(lStyle); //В первые два слова 
	*p++ = HIWORD(lStyle); //записываем стиль панели
	*p++ = 0; //В следующие две строки можно
	*p++ = 0; //расширенный стиль окна.
	*p++ = Items; //Количество органов управления панели
	*p++ = x; //Координата левого края панели
	*p++ = y; //Координата верхнего края панели
	*p++ = cx; //Ширина панели
	*p++ = cy; //Высота панели
	*p++ = 0; //Меню не подключено
	*p++ = 0; //Используем стандартный класс
	//Преобразуем Ansi-строку заголовка в строку Unicode

	int nChar = nCopyAnsiToWideChar(p, txt);
	p += nChar; //Смещаем указатель на количество символов
	//Выравниваем шаблон по границе слова WORD
	p = lpwAlign((LPWORD)p);
}

void DlgItemTemplate(PWORD& p, DWORD lStyle, int x, int y, int cx, int cy,
	WORD id, LPTSTR classname, LPCTSTR txt)
{
	*p++ = LOWORD(lStyle);
	*p++ = HIWORD(lStyle);
	*p++ = 0;
	*p++ = 0;
	*p++ = x;
	*p++ = y;
	*p++ = cx;
	*p++ = cy;
	*p++ = id;
	//Преобразуем Ansi-строку имени класса в строку Unicode
	int nChar = nCopyAnsiToWideChar(p, classname);
	*p += nChar;
	//Преобразуем Ansi-строку заголовка в строку Unicode
	if (lstrlen(txt) > 0)
		nChar = nCopyAnsiToWideChar(p, txt);
	else
		nChar = nCopyAnsiToWideChar(p, "");
	p += nChar;
	*p++ = 0; //Дополнительные данные не используем
	//Выравниваем шаблон по границе слова.
	p = lpwAlign((LPWORD)p);
}

#endif
apofioz вне форума Ответить с цитированием
Старый 04.01.2023, 19:20   #2
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

И код примера, самой первой панели, но он не собирается
Код:
#include<windows.h>
#include<tchar.h>
#include "CreateDlg.h"

#define ID_STATIC  2000
#define ID_BUTTON1 2001
#define ID_BUTTON2 2002
#define ID_BUTTON3 2003
#define ID_HELP    2004

BOOL       RegClass(WNDPROC, LPCTSTR, UINT);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);

int CreateDlg(HWND);

HINSTANCE hInstance = NULL;

TCHAR szMainClass[] = TEXT("WindowAppClass");

int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	MSG msg = { 0 };
	HWND hwnd = NULL;
	hInstance = hInst;

	if (!RegClass(WndProc, szMainClass, COLOR_DESKTOP))
		return FALSE;

	int wScreen = GetSystemMetrics(SM_CXSCREEN);
	int hScreen = GetSystemMetrics(SM_CYSCREEN);

	hwnd = CreateWindow(szMainClass, TEXT("Create a dialog box"),
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,
		0, 0, wScreen, hScreen, 0, 0, hInstance, NULL);
	if (!hwnd)
		return FALSE;

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

BOOL RegClass(WNDPROC proc, LPCTSTR szName, UINT brBackground)
{
	WNDCLASS wc = { 0 };
	wc.style = wc.cbClsExtra = wc.cbWndExtra = 0;
	wc.lpfnWndProc = proc;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(brBackground + 1);
	wc.lpszMenuName = (LPCTSTR)NULL;
	wc.lpszClassName = szName;
	return (RegisterClass(&wc) != 0);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_LBUTTONDOWN:
	{
		CreateDlg(hwnd);
		return 0;
	}
	case WM_DESTROY:
	{
		PostQuitMessage(0);
		return 0;
	}
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

int CreateDlg(HWND hwnd)
{
	TCHAR const caption[] = TEXT("Изменение режима работы приложения");
	TCHAR const stattxt[] = TEXT("Сейчас следует:");
	TCHAR const modeoff[] = TEXT("Завершить работу приложения");
	TCHAR const modedat[] = TEXT("Перезагрузить данные");
	TCHAR const modepsw[] = TEXT("Сменить имя пользователя");

	//Выдкляем блок памяти для записи шаблона
	WORD* p, * pdlgtemplate;
	pdlgtemplate = p = (PWORD)LocalAlloc(LPTR, 2000);

	//оПРЕДЕЛЯЕМ СРЕДНЮЮ ШТРИНУ И ВЫСОТУ ШРИФТА
	int cxChar, cyChar;
	{
		TEXTMETRIC tm;
		HDC hdc = GetDC(hwnd);
		GetTextMetrics(hdc, &tm);
		ReleaseDC(hwnd, hdc);
		cxChar = tm.tmAveCharWidth + 1;
		cyChar = tm.tmHeight + tm.tmExternalLeading;
	}

	//Опредеяем диалоговые единицы ширины и высоты
	DWORD dlgunit = GetDialogBaseUnits();
	int dlgwunit = LOWORD(dlgunit), dlghunit = HIWORD(dlgunit);

	//Пересчитываем габариты символов шрифта
	cxChar = cxChar * 4 / dlgwunit;
	cyChar = cyChar * 8 / dlghunit;

	int wDlg, hDlg, witem, hitem, left, top;
	//Записываем в шаблон данные панели
	DWORD lStyle = DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW |
		WS_CAPTION;
	wDlg = lstrlen(caption) * cxChar;
	hDlg = cyChar * 10;
	DlgTemplate(p, lStyle, 7, 0, 0, wDlg, hDlg, (LPSTR)caption);

	//Далее добавляем записи органов управления
	//1
	hitem = cyChar;
	top = left = hitem / 2;
	hitem += left;
	witem = (wDlg - left - left);
	lStyle = WS_CHILD | WS_VISIBLE | BS_GROUPBOX | WS_TABSTOP;
	DlgItemTemplate(p, lStyle, left, top, witem, 4 * hitem + left,
		ID_STATIC, (LPSTR)"button", (LPSTR)stattxt);

	//2
	witem = lstrlen(modeoff) * cxChar + 10;
	top += hitem;
	lStyle = BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP;
	DlgItemTemplate(p, lStyle, hitem, top, witem, hitem,
		ID_BUTTON1, (LPSTR)"button", (LPSTR)modeoff);

	//3
	witem = lstrlen(modedat) * cxChar + 10;
	top += hitem;
	lStyle = BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE;
	DlgItemTemplate(p, lStyle, hitem, top, witem, hitem,
		ID_BUTTON2, (LPSTR)"button", (LPSTR)modedat);

	//4
	witem = lstrlen(modepsw) * cxChar + 10;
	top += hitem;
	lStyle = BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE;
	DlgItemTemplate(p, lStyle, hitem, top, witem, hitem,
		ID_BUTTON3, (LPSTR)"button", (LPSTR)modepsw);

	//5
	witem = (wDlg - left - left - hitem - hitem) / 3;
	top += hitem + hitem / 2 + left;
	lStyle = BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP;
	DlgItemTemplate(p, lStyle, left, top, witem, hitem, IDOK,
		(LPSTR)"button", (LPSTR)"Да");

	//6
	lStyle = BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP;
	DlgItemTemplate(p, lStyle, left + witem + hitem, top, witem, hitem,
		IDCANCEL, (LPSTR)"button", (LPSTR)"Отмена");

	//7
	DlgItemTemplate(p, lStyle, left + witem + hitem + witem + hitem,
		top, witem, hitem, ID_HELP, (LPSTR)"button",
		(LPSTR)"Справка");

	//Создаём модальное диалоговое окно
	DialogBoxIndirect(hInstance, (LPDLGTEMPLATE)pdlgtemplate,
		hwnd, (DLGPROC)DlgProc);

	//Освобождаем занятый под шаблон блок памяти
	LocalFree(LocalHandle(pdlgtemplate));
	return 0;
}

LRESULT CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_COMMAND:
	{
		switch (LOWORD(wParam))
		{
		case IDOK:
		case IDCANCEL:
		{
			EndDialog(hDlg, TRUE);
			return TRUE;
		}
		}
	}
	}
	return FALSE;
}
Цитата:
error LNK2019: ссылка на неразрешенный внешний символ "int __cdecl nCopyAnsiToWideChar(unsigned short *,char const *)" (?nCopyAnsiToWideChar@@YAHPAGPBD@Z) в функции "void __cdecl DlgItemTemplate(unsigned short * &,unsigned long,int,int,int,int,unsigned short,wchar_t *,wchar_t const *)" (?DlgItemTemplate@@YAXAAPAGKHHHHGPA _WPB_W@Z).
Указание на символы, которые определены и могут подойти:
"int __cdecl nCopyAnsiToWideChar(unsigned short *,wchar_t const *)" (?nCopyAnsiToWideChar@@YAHPAGPB_W@Z )
error LNK2019: ссылка на неразрешенный внешний символ "void __cdecl DlgTemplate(unsigned short * &,unsigned long,int,int,int,int,int,char *)" (?DlgTemplate@@YAXAAPAGKHHHHHPAD@Z) в функции "int __cdecl CreateDlg(struct HWND__ *)" (?CreateDlg@@YAHPAUHWND__@@@Z).
Указание на символы, которые определены и могут подойти: "void __cdecl DlgTemplate(unsigned short * &,unsigned long,int,int,int,int,int,wchar_t const *)" (?DlgTemplate@@YAXAAPAGKHHHHHPB_W@Z )
error LNK2019: ссылка на неразрешенный внешний символ "void __cdecl DlgItemTemplate(unsigned short * &,unsigned long,int,int,int,int,unsigned short,char *,char *)" (?DlgItemTemplate@@YAXAAPAGKHHHHGPA D1@Z) в функции "int __cdecl CreateDlg(struct HWND__ *)" (?CreateDlg@@YAHPAUHWND__@@@Z).
Указание на символы, которые определены и могут подойти:
"void __cdecl DlgItemTemplate(unsigned short * &,unsigned long,int,int,int,int,unsigned short,wchar_t *,wchar_t const *)" (?DlgItemTemplate@@YAXAAPAGKHHHHGPA _WPB_W@Z)

Последний раз редактировалось apofioz; 04.01.2023 в 19:22.
apofioz вне форума Ответить с цитированием
Старый 04.01.2023, 22:38   #3
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,355
По умолчанию

Обратите внимание на
Код:
int nCopyAnsiToWideChar(LPWORD lpWCStr, LPCSTR lpAnsi)
int nCopyAnsiToWideChar(LPWORD lpWCStr, LPCTSTR lpAnsi)
Это не одно и тоже.
waleri вне форума Ответить с цитированием
Старый 04.01.2023, 22:56   #4
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

ваша помощь просто "неоценима".

Последний раз редактировалось apofioz; 05.01.2023 в 15:00.
apofioz вне форума Ответить с цитированием
Старый 11.01.2023, 14:24   #5
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Интересно, а здесь почему падает программа, когда пытаюсь открыть диалоговую панель? Такое ощущение, что происходит зацикливание.
EditTest.rar
Ошибка:
Unhandled exception at 0x7c8024f9 in *.exe: 0xC00000FD: Stack overflow.
apofioz вне форума Ответить с цитированием
Старый 11.01.2023, 18:14   #6
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,770
По умолчанию

Вы не только файл проеккта прикладывайте, а еще и исходник.
p51x вне форума Ответить с цитированием
Старый 11.01.2023, 18:41   #7
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,355
По умолчанию

Цитата:
Сообщение от apofioz Посмотреть сообщение
ваша помощь просто "неоценима".
Я не виноват, что вы решили читать "Войну и Мир" не зная алфавита...
Выучите основы, потом лезьте в дебри.
waleri вне форума Ответить с цитированием
Старый 11.01.2023, 18:54   #8
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от p51x Посмотреть сообщение
Вы не только файл проеккта прикладывайте, а еще и исходник.
Сделано.
EditTest.rar
apofioz вне форума Ответить с цитированием
Старый 11.01.2023, 18:58   #9
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Я не виноват, что вы решили читать "Войну и Мир" не зная алфавита...
Ну, я бы не сказал, что я совсем уж лох, а по поводу того, что не знаю много, кто бы с этим спорил, но я думал, что тематические форумы для того и существуют, что бы расти вверх, а не опускаться вниз. Я спрашиваю, если мне не понятно я переспрашиваю, разве это не то, что должно быть на форуме.
apofioz вне форума Ответить с цитированием
Старый 11.01.2023, 19:26   #10
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Выучите основы, потом лезьте в дебри.
Уже давно пора лезть в дебри, опушку топтать надоело. Что конкретно я, по вашему, не знаю... Я за себя знаю, например то, что с указателями я не разобрался, не понимаю я их до конца и что теперь, не жить.
apofioz вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Панель инструментов Лия92 Помощь студентам 0 12.12.2010 16:17
Панель инструментов для картинок в IE ! chepuxa Софт 0 04.10.2009 12:10
Панель инструментов VBA Lyubov1990 Microsoft Office Excel 5 04.06.2009 09:52
Вложенная панель инструментов. haros Microsoft Office Excel 7 16.03.2009 14:38
Панель инструментов как в office _victor Компоненты Delphi 0 01.04.2008 07:06