Rzutowanie LPCTSTR na int (do enum) i proces odwrotny

0

Cześć, chciałem się upewnić w jednej rzeczy, bo rzutowanie nie jest moją mocną stroną ;).
Pytanie dot. mojego wrappera na WinApi.

Zrobiłem sobie enum-a CursorType, w którym mam odpowiedniki różnych typów cursorów systemowych (np. ARROW, WAIT, HAND etc. - odpowiedniki IDC_ARROW, IDC_WAIT etc.).
W zależności od tego, który typ zostanie wybrany chcę go ustawić w oknie przy pomocy funkcji LoadCursor(). Problem w tym, że windowsowe wersje tych zmiennych są wskaźnikami (LPCTSTR) a nie int-ami i nie mogę przypisać ich bezpośrednio do moich enumów.
Zastanawiam się więc nad rzutowaniem ich do int, by uniknąć switch-a.

Ogólnie koncepcja jest taka: w enum-ie rzutuję IDC_NAZWA_CURSORA na int a w funkcji LoadCursor rzutuję mojego enuma na (LPCTSTR). Wygląda to mniej więcej tak:

		enum CursorType
			{
			ARROW = (int)IDC_ARROW,
			WAIT = (int)IDC_WAIT,
			//...
			
			};
//...
void SetSystemCursor(CursorType cursor)
	{
	if(hWnd)
		{
		LoadCursor(NULL, (LPCTSTR)cursor);
		}
	}

No i teraz pytanie:

  1. czy to jest bezpieczne?
  2. czy nie powinienem w enumie stosować dynamic_cast lub innego odpowiednika?

Z góry dzięki za pomoc.

0

To w ogóle działa? :|
Użyj tablicy/mapy.

0
Patryk27 napisał(a):

To w ogóle działa? :|

Czy działa to jeszcze nie wiem - nie miałem możliwości jeszcze sprawdzić. Na pewno się kompiluje.
Natomiast dlaczego miałoby nie działać? W końcu bit-y są nienaruszone.

Patryk27 napisał(a):

Użyj tablicy/mapy.

Co masz na myśli? W jaki sposób?

1

Co masz na myśli? W jaki sposób?

enum CursorType
{
	ARROW = 0, 
	WAIT, 
	HAND,
	...
};


const LPCTSTR CursorType_map[] = { IDC_ARROW, IDC_WAIT, IDC_HAND, ... };


void SetSystemCursor(CursorType cursor)
{
	if(hWnd)
	{
		LoadCursor(NULL, CursorType_map[ cursor ] );
	}
}
1

Nie znam zbyt dobrze WINAPI, ale:

  • LPCTSTR jest wskaźnikiem. Od strony logicznej w/g mnie nie ma to sensu,
  • ale z tego co rozumiem, wartości w tym przypadku generowane są za pomocą MAKEINTRESOURCE i trzymają faktycznie wartości liczbowe (w zakresie 16-bitowym?).

Od strony standardu, wydaje mi się, że to będzie działanie OK (w znaczeniu zdefiniowane i działające tak jak tego chcesz) jeśli pracujesz na architekturze gdzie sizeof(int)sizeof(LPCTSTR) (hint: Windows x64 nie jest taką architekturą) lub tam gdzie wartości trzymane w ten sposób nie wykraczają poza zakres wartości int (wydaje się, że wszędzie).

Mimo wszystko, wydaje mi się to niezbyt czyste - musisz używać castowania w stylu C lub reinterpret_cast, a jak pod jakimś z tych makr w przyszłości pojawi się większa liczba niż zakres inta to jesteś udupiony. Raczej użyłbym mapowania wartości w prosty, przyjemny i wydajny sposób za pomocą std::unordered_map.

2

Do LoadCursor podajemy wskaźnik na stringa z nazwą albo rzutowane (makrem MAKEINTRESOURCE) id resource'a.
To taki hack, jakiego pełno w WinAPI.

Wartość ID wynosi maksymalnie 65535, a minimalna wartość wskaźnika pod Windows (oprócz NULL) to 65536. Zakresy więc nie nakładają się, a hack działa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1