C++ przycisk- tooltip

0

Witam,

Piszę sobie w miarę prosty programik okienkowy w C++ i utknąłem próbując dodać podpowiedź do przycisku. Niestety podpowiedź nie chce się pojawić. Przeszukałem sporo stron, ale nigdzie nie znalazłem rozpisanego pełnego przykładu (np. kodu źródłowego który można przejrzeć i przeanalizować całościowo).

W include mam dodane:

#include <commctrl.h>

Podlinkowałem także bibliotekę "comctl32.lib".

Deklaracje IDków przycisków:

#define WINDOWS_BUTTON	101	
#define TB_POLYNOMIAL_EXPRESSION	102	
#define TB_POLYNOMIAL_FILE_PATH	103	
#define TB_EPSILON_VALUE 104
#define TB_START_POINT 105
#define TB_CALCULATIONS 106
#define CB_MODE 107
#define BTN_CLEAR_CALCFIELD 108	

Deklaracja uchwytów do guzików:

HWND tb_polynomial_expression;
HWND tb_start_point;
HWND tb_epsilon_value;
HWND tb_calculations;
HWND cb_mode;
HWND btn_calculate;
HWND btn_clear_calcfield;

(nie wiem czemu pomimo tego że wszystkie kontrolki pojawiają się, część pól ma wartość NULL?)

W metodzie InitInstance generuje kontrolki w okienku (wszystkie poza tooltipem pojawiają się zgodnie z moimi oczekiwaniami):

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{	
	//InitCommonControls();
	HWND hWnd;

	hInst = hInstance; // Store instance handle in our global variable

	hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 450, 665, NULL, NULL, hInstance, NULL);
	HBRUSH brush = CreateSolidBrush(RGB(240,240,240));
	SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG)brush);
	cb_mode = CreateWindowEx(0, L"BUTTON", L"Load from file", WS_VISIBLE | WS_CHILD | ES_LEFT | BS_AUTOCHECKBOX, 220, 10, 120, 20,  hWnd,  (HMENU)CB_MODE, hInst, NULL);
	CreateWindow(L"STATIC",L"polynomial expression:", WS_VISIBLE | WS_CHILD | SS_LEFT, 10, 10, 200, 20,hWnd, NULL, hInst, NULL);
	tb_polynomial_expression = CreateWindowEx( 0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 40, 300, 20, hWnd, (HMENU) TB_POLYNOMIAL_EXPRESSION, hInst, NULL );
	CreateWindow(L"STATIC",L"Start point:", WS_VISIBLE | WS_CHILD | SS_LEFT, 10, 70, 200, 20,hWnd, NULL, hInst, NULL);
	tb_start_point = CreateWindowEx( 0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 100, 300, 20, hWnd, (HMENU) TB_START_POINT, hInst, NULL );
	CreateWindow(L"STATIC",L"Epsilon value:", WS_VISIBLE | WS_CHILD | SS_LEFT, 10, 130, 200, 20,hWnd, NULL, hInst, NULL);
	tb_epsilon_value = CreateWindowEx( 0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 160, 300, 20, hWnd, (HMENU) TB_EPSILON_VALUE, hInst, NULL );
	btn_calculate = CreateWindowEx( 0, L"BUTTON", L"Calculate", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 190, 150, 30, hWnd, (HMENU) WINDOWS_BUTTON, hInst, NULL );
	CreateWindow(L"STATIC",L"Calculations logs:", WS_VISIBLE | WS_CHILD | SS_LEFT, 10, 230, 200, 20,hWnd, NULL, hInst, NULL);
	tb_calculations = CreateWindowEx( 0, L"EDIT", NULL,  WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL, 10, 260, 400, 300, hWnd, (HMENU) TB_CALCULATIONS, hInst, NULL );
	btn_clear_calcfield = CreateWindowEx( 0, L"BUTTON", L"Clear logs", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 580, 150, 30, hWnd, (HMENU) BTN_CLEAR_CALCFIELD, hInst, NULL );
	CreateTooltip(btn_calculate,hInst,hWnd);
	if (!hWnd)
	{
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
	return TRUE;
}

Natomiast metoda CreateToolTip wygląda następująco:

void CreateTooltip(HWND hParent, HINSTANCE hInstance, HWND hMainWin)
{
	HWND hwndTT = CreateWindowEx( WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hParent, NULL, hInstance, NULL );
	SetWindowPos( hwndTT, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
	TOOLINFO ti;
	ti.cbSize = sizeof( TOOLINFO );
	ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
	ti.hwnd = hMainWin;
	ti.hinst = NULL;
	ti.uId =( UINT_PTR ) hParent;
	ti.lpszText = L"To jest podpowiedz...";
	RECT rect;
	GetClientRect( hParent, & rect );
	ti.rect.left = rect.left;
	ti.rect.top = rect.top;
	ti.rect.right = rect.right;
	ti.rect.bottom = rect.bottom;
	SendMessage( hwndTT, TTM_ADDTOOL, 0,( LPARAM ) & ti );
}

Czy ktoś kto bawił się tooltipami i jest w tym bieglejszy niż ja mógłby podzielić się jakimś pełnym przykładem (np. kodem źródłowym)? :) Wydaje mi się, że po prostu generuje tego tooltipa w nieodpowiednim miejscu.

Kod piszę w VS 2012.

Z góry dziękuję za pomoc!

0
ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
...

ti.rect.left = rect.left;
ti.rect.top = rect.top;
ti.rect.right = rect.right;
ti.rect.bottom = rect.bottom;
w dokumentcji o TOOLINFO::rect napisał(a)

If uFlags includes the TTF_IDISHWND flag, this member is ignored.

0

Niestety skasowanie tej flagi nie pomogło.

W czasie debugowania kodu w momencie wywołania funkcji tworzącej tooltipa na zmiennej btn_calculate oraz hWnd mam:
unused = <Unable to read memory>

Może to jest przyczyną?

0

Przyczyną jest to, że debugger oba uchwyty traktuje jak wskaźniki, choć wskaźnikami de facto nie są - stąd problem w odczycie pamięci, na którą (rzekomo) wskazują.

Wracając do tematu. Spróbuj tak:

	HWND hwndTT = CreateWindowEx( NULL, 
								TOOLTIPS_CLASS, 
								NULL, 
								WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, 
								CW_USEDEFAULT, 
								CW_USEDEFAULT, 
								CW_USEDEFAULT, 
								CW_USEDEFAULT, 
								hParent, 
								NULL, 
								hInstance, 
								NULL );

Wywal wywołanie SetWindowPos.

0

Niestety tooltip wciąż się nie pojawia.

1
#define _WIN32_WINNT 0x501
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>

#pragma comment(lib, "comctl32.lib")

#pragma comment(linker, "/manifestdependency:\"type='win32' \
	name='Microsoft.Windows.Common-Controls' \
	version='6.0.0.0' \
	processorArchitecture='*' \
	publicKeyToken='6595b64144ccf1df' \
	language='*'\"")

LRESULT __stdcall WndProc(HWND, UINT, WPARAM, LPARAM);

int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int nCmdShow)
{
	InitCommonControls();

	WNDCLASS wc;
	ZeroMemory(&wc, sizeof(wc));
	wc.lpfnWndProc = WndProc;
	wc.hInstance = hInstance;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
	wc.lpszClassName = L"{556E7654-976E-484c-8A00-A40B314ABA69}";

	LOGFONT lf;
	ZeroMemory(&lf, sizeof(lf));
	wcscpy_s(lf.lfFaceName, L"Tahoma");
	lf.lfHeight = -11;
	HFONT font = CreateFontIndirect(&lf);

	ATOM atom = RegisterClass(&wc);
	HWND hwnd = CreateWindow(
		MAKEINTATOM(atom),
		L"Test",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		400, 300,
		(HWND)NULL,
		(HMENU)NULL,
		hInstance,
		(LPVOID)NULL
	);

	HWND but = CreateWindow(
		WC_BUTTON,
		L"&Nic",
		WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
		163, 122,
		75, 23,
		hwnd,
		(HMENU)0,
		hInstance,
		(LPVOID)NULL
	);
	SetWindowFont(but, font, FALSE);

	HWND tip = CreateWindow(
		TOOLTIPS_CLASS,
		L"",
		WS_POPUP | TTS_ALWAYSTIP, // | TTS_BALLOON,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		hwnd,
		(HMENU)0,
		hInstance,
		(LPVOID)NULL
	);

	TOOLINFO ti;
	ZeroMemory(&ti, sizeof(ti));
	ti.cbSize = sizeof(ti);
	ti.hwnd = hwnd;
	ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
	ti.uId = (UINT_PTR)but;
	ti.lpszText = L"Ten przycisk nic nie robi";
	SendMessage(tip, TTM_ADDTOOL, 0, (LPARAM)&ti);

	SetFocus(but);
	ShowWindow(hwnd, nCmdShow);

	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
		if (!IsDialogMessage(hwnd, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	return msg.wParam;
}

LRESULT __stdcall WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	return 0;
}
0

W czym pisałeś kod?

0

Przetestowałem powyższy kod i tooltipy pojawiły się.

Kluczem do rozwiązania zagadki był brak poniższej linijki:

#pragma comment(linker, "/manifestdependency:\"type='win32' \
    name='Microsoft.Windows.Common-Controls' \
    version='6.0.0.0' \
    processorArchitecture='*' \
    publicKeyToken='6595b64144ccf1df' \
    language='*'\"")

Zauważyłem, że linijka ta generuje jednocześnie "przyjaźniejszy" wygląd przycisków i ogólnie kontrolek windowsowych. W jaki sposób przywrócić "płaski" styl guzików? I drugie pytanie: czy da się zmienić kolor dymka z podpowiedzią?

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