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

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

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

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

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

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

Здравствуйте! Хочется сразу перейти к делу, допустим, что есть окно в котором нужно нарисовать мишень, мишень состоит из десяти полей. Далее предлагается с помощью стандартной панели выбора цвета выбрать цвет для определённого поля мишени, как это реализовывать не уточняется, и так как нет никаких конкретных инструкций я решил сделать так. Создать 10-ть регионов, по клику по одному из них должна вызваться диалоговая панель выбора цвета, и после выбора цвета, это поле должно окраситься в этот цвет. Но как отловить клик мыши так, что бы точно знать в каком поле был клик... Попытка облегчить задачу с помощью создания эллиптических регионов не увенчалась успехом т.к. нет однозначного ответа в каким именно регионе была нажата кнопка мышки. Думаю делать так: зная радиус и координаты(клик мыши) можно попробовать через т. Пифагора aqrt(x*x + y*y) <= r*r, но тоже ничего путёвого не получается, пока что, не получается. Соответственно в этом и заключается вопрос, как сделать отлов кликов мыши так, чтобы точно знать, в каком поле мишени ты кликнул.

Мишень создаю так:
Код:
case WM_PAINT:
		{
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(hwnd, &ps);
			
			int OldBk = SetBkMode(hdc, TRANSPARENT);
			int OldBkColor = SetBkColor(hdc, crColorRgn);
			hPen = CreatePen(PS_SOLID, 2, RGB(0,0,0));
			hOldPen = (HPEN)SelectObject(hdc, hPen);
			for(int i = 0; i < 10; ++i)
			{
				Ellipse(hdc, rcRgn[i].left, rcRgn[i].top, 
				             rcRgn[i].right, rcRgn[i].bottom);
			}
			SetBkMode(hdc, OldBk);
			SetBkMode(hdc, OldBkColor);
			SelectObject(hdc, hOldPen);
			
			
			EndPaint(hwnd, &ps);
			return 0;
		}
Думаю отлавливать клики мыши так:
Код:
case WM_LBUTTONDOWN:
		{
			int x = LOWORD(lParam);
			int y = HIWORD(lParam);
			for(int i = 0; i < 10; ++i)
			{
				if(PtInRegion(hRgn[i], x, y))
				{
					TCHAR szStr[64];
					_stprintf_s(szStr, 64, 
					TEXT("Point(x = %d, y = %d) In a Region %d"),
					x, y, (i+1));
					MessageBox(NULL, szStr, TEXT("Message"), MB_OK);
				}
				else
				{
					TCHAR szStr[64];
					_stprintf_s(szStr, 64, 
					TEXT("Point(x = %d, y = %d) In not a Region %d"),
					x, y, (i + 1));
					MessageBox(NULL, szStr, TEXT("Message"), MB_OK);
				}
			}
			return 0;
		}
Есть мысли по этому поводу.
apofioz вне форума Ответить с цитированием
Старый 17.03.2023, 22:36   #2
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

А что не получается с формулой дистанции (радиуса)
aim_minor_radius <= sqrt(pow(mouse_x - aim_center_x, 2) + pow(mouse_y - aim_center_y, 2)) < aim_major_radius

Можно обойтись и без sqrt

aim_minor_radius * aim_minor_radius <= pow(mouse_x - aim_center_x, 2) + pow(mouse_y - aim_center_y, 2) < aim_major_radius * aim_minor_radius

Последний раз редактировалось macomics; 17.03.2023 в 22:40.
macomics вне форума Ответить с цитированием
Старый 17.03.2023, 22:49   #3
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
aim_center_x
Это координата центра, я правильна понял? Видимо вот этой корректировки мне и не хватало.
pow(mouse_x - aim_center_x, 2) + pow(mouse_y - aim_center_y, 2)
apofioz вне форума Ответить с цитированием
Старый 17.03.2023, 23:04   #4
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
Можно обойтись и без sqrt
Какая разница, умножение тоже много тактов процессора требует.
apofioz вне форума Ответить с цитированием
Старый 17.03.2023, 23:31   #5
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

В случае с целыми числами два умножение и целочисленных сравнения занимает в разы меньше, чем вещественная операция вычисления квадратного корня и две операции сравнения вещественных чисел.
macomics вне форума Ответить с цитированием
Старый 17.03.2023, 23:47   #6
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
В случае с целыми числами два умножение и целочисленных сравнения занимает в разы меньше,
В разы? Ну что ж, спорить не стану, но я в этом сильно сомневаюсь
А по стилистике того решения, которое я пытаюсь реализовать, правильное ли оно или лучше делать как-то иначе. Я понимаю, что вкусы у всех разные, но всё же...
apofioz вне форума Ответить с цитированием
Старый 20.03.2023, 17:08   #7
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

И в ДОПОЛНЕНИЕ к теме т.к. задание тоже, то спрошу здесь, Если мишень нужно нарисовать на временном окне, которой находится на диалоговой панели, я думаю, что прорисовка мишени и изменение цвета полей мишени нужно производить в функции окна, которое встроено в диалоговую панель, не в функции же диалоговой панели, но возникла какая-то ошибка, поуа что решить её не могу. Вот часть кода:
Код:
int CreateDlg(HWND hwnd)
{
	const TCHAR szCaption[] = TEXT("TARGET...");

	WORD* p, * pdlgTempl;
	p = pdlgTempl = (LPWORD)LocalAlloc(LPTR, 1024);
	if (!p)
	{
		MessageBox(NULL, TEXT("Can't allocated memory"),
			TEXT("Error"), MB_OK);
		return 1;
	}
	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 dwBaseUnit = GetDialogBaseUnits();
	cxChar = cxChar * 4 / LOWORD(dwBaseUnit);
	cyChar = cyChar * 8 / HIWORD(dwBaseUnit);

	DWORD lStyle = DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION;
	int wDlg, hDlg, cxWnd, cyWnd, left, top;
	wDlg = 320;
	hDlg = 240;
	RECT rc;
	GetClientRect(hwnd, &rc);
	left = ((rc.right * 4 / LOWORD(dwBaseUnit)) >> 1) - (wDlg >> 1);
	top = ((rc.bottom * 8 / HIWORD(dwBaseUnit)) >> 1) - (hDlg >> 1);

	LPDLGTEMPLATE lpdt;
	LPDLGITEMTEMPLATE lpdit;
	LPWSTR szDst;
	LPCWSTR szSrc;
	lpdt = (LPDLGTEMPLATE)p;
	lpdt->style = lStyle;
	lpdt->dwExtendedStyle = 0;
	lpdt->cdit = 1;
	lpdt->x = left;
	lpdt->y = top;
	lpdt->cx = wDlg;
	lpdt->cy = hDlg;
	p = (LPWORD)(lpdt + 1);
	*p++ = 0;
	*p++ = 0;
	szDst = (LPWSTR)(p);
	szSrc = szCaption;
	for (; *szDst++ = *szSrc++;)
		;
	p = (LPWORD)szDst;
	p = lpwAlign((LPWORD)p);

	//1
	left = 10;
	top = 10;
	cxWnd = wDlg - 20;
	cyWnd = hDlg - 20;
	lStyle = WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_BORDER | WS_DLGFRAME;

	lpdit = (LPDLGITEMTEMPLATE)p;
	lpdit->style = lStyle;
	lpdit->dwExtendedStyle = 0;
	lpdit->x = left;
	lpdit->y = top;
	lpdit->cx = cxWnd;
	lpdit->cy = cyWnd;
	lpdit->id = ID_POPUPWINDOW;
	szDst = (LPWSTR)(lpdit + 1);
	szSrc = szPopupClass;
	for (; *szDst++ = *szSrc++;)
		;
	szSrc = TEXT("\0");
	for (; *szDst++ = *szSrc++;)
		;
	p = (LPWORD)szDst;
	*p++ = 0;
	p = lpwAlign((LPWORD)p);

	int ret;
//Когда пытаюсь открыть стандартную диалоговую панель выбора цвета, попадаю сюда,
//с ошибкой "Вызвано исключение по адресу 0x76F66EB1 (comdlg32.dll) в Ex6_10.exe: //0xC0000005: нарушение прав доступа при чтении по адресу 0x00000000."

	ret = DialogBoxIndirect(hInstance, (LPCDLGTEMPLATE)pdlgTempl,
		hwnd, (DLGPROC)DlgProc);
	if (ret == -1)
		DWORD er = GetLastError();
	LocalFree(LocalHandle(pdlgTempl));

	return ret;
}
Код:
LRESULT CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static HWND hPop;
	switch (msg)
	{
		case WM_INITDIALOG:
		{
			hPop = GetDlgItem(hDlg, ID_POPUPWINDOW);
			return TRUE;
		}
		case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
				case IDCANCEL:
				{
					EndDialog(hDlg, TRUE);
					return TRUE;
				}
				default:
					break;
			}
		}
	}
	return FALSE;
}
Код:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static HMENU hMainMenu, hPopMenu;
	static MENUITEMINFO mii;
	switch (msg)
	{
	case WM_CREATE:
	{
		hMainMenu = CreateMenu();
		hPopMenu = CreatePopupMenu();
		SetMenu(hwnd, hMainMenu);
		mii.cbSize = sizeof(mii);
		mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_SUBMENU;
		mii.fType = MFT_STRING;
		mii.fState = MFS_ENABLED;
		mii.wID = CM_TARGET_OPEN;
		mii.hSubMenu = NULL;
		mii.dwTypeData = (LPTSTR)TEXT("Open target");
		mii.cch = _tcslen(TEXT("Open target"));

		InsertMenuItem(hPopMenu, CM_TARGET_OPEN, FALSE, &mii);

		mii.fType = MFT_SEPARATOR;
		mii.fState = MFS_ENABLED;
		mii.wID = 0;
		mii.hSubMenu = NULL;
		mii.dwTypeData = (LPTSTR)NULL;
		mii.cch = 0;
		InsertMenuItem(hPopMenu, 0, FALSE, &mii);

		mii.fType = MFT_STRING;
		mii.fState = MFS_ENABLED;
		mii.wID = CM_TARGET_QUIT;
		mii.hSubMenu = NULL;
		mii.dwTypeData = (LPTSTR)TEXT("Exit");
		mii.cch = _tcslen(TEXT("Exit"));
		InsertMenuItem(hPopMenu, CM_TARGET_QUIT, FALSE, &mii);

		mii.fType = MFT_STRING;
		mii.fState = MFS_ENABLED;
		mii.wID = 0;
		mii.hSubMenu = hPopMenu;
		mii.dwTypeData = (LPTSTR)TEXT("TARGET");
		mii.cch = _tcslen(TEXT("TARGET"));
		InsertMenuItem(hMainMenu, 0, TRUE, &mii);

		DrawMenuBar(hwnd);

		return 0;
	}
	case WM_COMMAND:
	{
		switch (LOWORD(wParam))
		{
		case CM_TARGET_OPEN:
		{
			CreateDlg(hwnd);
			return 0;
		}
		case CM_TARGET_QUIT:
		{
			DestroyWindow(hwnd);
			return 0;
		}
		}
		return 0;
	}
	case WM_DESTROY:
	{
		PostQuitMessage(0);
		return 0;
	}
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}
apofioz вне форума Ответить с цитированием
Старый 20.03.2023, 17:08   #8
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

//Здесь я хочу рисовать мишень, по клику мыши выбрать цвет из стандартной диалоговой панели выбора цвета и раскрасить поле мишени по которому я кликнул в этот цвет.
Код:
LRESULT CALLBACK PopProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static int cxClient, cyClient;
	static HRGN hRgn[10];
	static RECT rcRgn[10];
	static HPEN hPen, hOldPen;
	const int indent = 0;
	static int radius, rad;
	static COLORREF lpCustColors[16], rgbResult = RGB(255, 255, 255);
	static COLORREF crCellTarget[10]; //Здесь цвет для каждого поля мишени
	static CHOOSECOLOR cc;
	static POINT ptCenter;

	switch (msg)
	{
	case WM_CREATE:
	{
		ZeroMemory(&cc, sizeof(CHOOSECOLOR));
		cc.lStructSize = sizeof(cc);
		cc.hwndOwner = hwnd;
		cc.hInstance = NULL;
		cc.rgbResult = rgbResult;
		cc.Flags = CC_ANYCOLOR | CC_RGBINIT;

		for (int i = 0; i < 10; ++i)
		{
			//hRgn[i] = CreateEllipticRgn(0, 0, 0, 0);
			crCellTarget[i] = GetClassLong(hwnd, GCL_HBRBACKGROUND);
		}
		return 0;
	}
	case WM_SIZE:
	{
		cxClient = LOWORD(lParam);
		cyClient = HIWORD(lParam);
		int d = (cxClient > cyClient) ? cyClient : cxClient;
		rad = radius = (d >> 1);
		rad /= 10; //Значение промежутка между эллипсами(или регионами, как удобнее).
		ptCenter.x = (cxClient >> 1);
		ptCenter.y = (cyClient >> 1);

		int l = (cxClient >> 1) - (d >> 1);
		int t = indent;
		int r = (cxClient >> 1) + (d >> 1);
		int b = cyClient - indent;
		for (int i = 0; i < 10; ++i)
		{
			SetRect(&rcRgn[i], l, t, r, b);
			hRgn[i] = CreateEllipticRgn(l, t, r, b);
			l += rad;
			t += rad;
			r -= rad;
			b -= rad;
		}
		return 0;
	}
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);

		int OldBk = SetBkMode(hdc, TRANSPARENT);
		//int OldBkColor = SetBkColor(hdc, crColorRgn);
		hPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
		hOldPen = (HPEN)SelectObject(hdc, hPen);
		TCHAR szNum = '1';
		HBRUSH hBrush, hOldBrush;
		for (int i = 0; i < 10; ++i)
		{
			Ellipse(hdc, rcRgn[i].left, rcRgn[i].top,
				rcRgn[i].right, rcRgn[i].bottom);
			
			int OldAlign = SetTextAlign(hdc, TA_CENTER);
//Если это последняя ячейка-поле, то нужно сместить rad так чтобы 10-как была по середине 
//последнего эллипса. 
			if (i == 9)
				TextOut(hdc, rcRgn[i].left + rad,
					ptCenter.y, (LPCTSTR)szNums[i], 2);
			else
			{
				TextOut(hdc, rcRgn[i].left + (rad >> 1),
					ptCenter.y, (LPCTSTR)szNums[i], 1);
				TextOut(hdc, rcRgn[i].right - (rad >> 1),
					ptCenter.y, (LPCTSTR)szNums[i], 1);
			}

			SetTextAlign(hdc, OldAlign);
		}
		for (int i = 0; i < 10; ++i)
		{
			hBrush = CreateSolidBrush(crCellTarget[i]);
			hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);

			/*ExtFloodFill(hdc, (rcRgn[i].right >> 1),
				rcRgn[i].top + (rad >> 1),
				RGB(0, 0, 0), FLOODFILLBORDER);*/

			SelectObject(hdc, hOldBrush);
			DeleteObject(hBrush);
		}
		SetBkMode(hdc, OldBk);
		//SetBkColor(hdc, OldBkColor);
		SelectObject(hdc, hOldPen);


		EndPaint(hwnd, &ps);
		return 0;
	}
	case WM_LBUTTONDOWN:
	{
		int x = LOWORD(lParam);
		int y = HIWORD(lParam);
		int iMaxRad = radius;
		int iMinRad = iMaxRad - rad;

		int iPowMaxRad = iMaxRad * iMaxRad;
		int iPowMinRad = iMinRad * iMinRad;
		x -= ptCenter.x;
		y -= ptCenter.y;
		int i;
		int len = x * x + y * y;
		for (i = 0; i < 10; ++i)
		{
			if (len >= iPowMinRad && len <= iPowMaxRad)
			{
				break;
			}
			else
			{
				iMaxRad = iMinRad;
				iMinRad -= rad;

				iPowMaxRad = iMaxRad * iMaxRad;
				iPowMinRad = iMinRad * iMinRad;

			}
		}
		if (i < 10)
		{
			//Ошибка вылезает отсюда
			if (ChooseColor(&cc) == TRUE)
			{
				crCellTarget[i] = cc.rgbResult;
				InvalidateRect(hwnd, &rcRgn[0], TRUE);
			}
			else
			{
				DWORD er = CommDlgExtendedError();
				if (er == CDERR_DIALOGFAILURE)
				{
					MessageBox(NULL, TEXT("CDERR_DIALOGFAILURE"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_FINDRESFAILURE)
				{
					MessageBox(NULL, TEXT("CDERR_FINDRESFAILURE"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_MEMLOCKFAILURE)
				{
					MessageBox(NULL, TEXT("CDERR_MEMLOCKFAILURE"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_INITIALIZATION)
				{
					MessageBox(NULL, TEXT("CDERR_INITIALIZATION"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_NOHINSTANCE)
				{
					MessageBox(NULL, TEXT("CDERR_NOHINSTANCE"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_NOHOOK)
				{
					MessageBox(NULL, TEXT("CDERR_NOHOOK"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_LOADRESFAILURE)
				{
					MessageBox(NULL, TEXT("CDERR_LOADRESFAILURE"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_NOTEMPLATE)
				{
					MessageBox(NULL, TEXT("CDERR_NOTEMPLATE"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_LOADSTRFAILURE)
				{
					MessageBox(NULL, TEXT("CDERR_LOADSTRFAILURE"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_STRUCTSIZE)
				{
					MessageBox(NULL, TEXT("CDERR_STRUCTSIZE"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else if (er == CDERR_MEMALLOCFAILURE)
				{
					MessageBox(NULL, TEXT("CDERR_MEMALLOCFAILURE"),
						TEXT("Error"), MB_OK);
					return 0;
				}
				else
				{
					MessageBox(NULL, TEXT("UNKNOWN ERROR"),
						TEXT("Error"), MB_OK);
					return 0;
				}
			}
			TCHAR szStr[64];
			_stprintf_s(szStr, 64,
				TEXT("Point(x = %d, y = %d) In a Region  %d"),
				x, y, (i + 1));
			MessageBox(NULL, szStr, TEXT("Message"), MB_OK);
		}
		/*else
		{
			TCHAR szStr[64];
			_stprintf_s(szStr, 64,
			TEXT("Point(x = %d, y = %d) In not a Region"),
			x, y);
			MessageBox(NULL, szStr, TEXT("Message"), MB_OK);
		}*/

		return 0;
	}
	case WM_DESTROY:
	{
		for (int i = 0; i < 10; ++i)
			DeleteObject(hRgn[i]);
		PostQuitMessage(0);
		return 0;
	}
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}
apofioz вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[C++] Работа с мышью koshkarjov Помощь студентам 0 14.10.2010 22:36
Работа с мышью Amery Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 4 28.05.2008 21:19
Win Api, работа с мышью Petrr Win Api 2 26.04.2008 19:58