I am newbie in c++ win32 Programming and I am using visual studio 2013 on Windows 7 X64 SP1.
I have used this code in link below to create tooltip for a button in DialogBox and successfully it worked.
Tooltip for button
but when I want to change the background color or foreground color , it does not work and it shows the default colors.
SendMessage(hwndTip, TTM_SETTIPBKCOLOR, 0xFF326FD8, 0);
//SendMessage(hwndTip, TTM_SETTIPBKCOLOR, (WPARAM)CreateSolidBrush(RGB(255,255, 255), 0);
SendMessage(hwndTip, TTM_SETTIPTEXTCOLOR, (WPARAM)CreateSolidBrush(RGB(255,255, 255)), 0);
Because in this link :
http://msdn.microsoft.com/en-us/library/windows/desktop/bb760411%28v=vs.85%29.aspx
the MSDN said that "When visual styles are enabled, this message has no effect." so I changed the
HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON |TTS_USEVISUALSTYLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hDlg, NULL,
hInst, NULL);
to :
HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hDlg, NULL,
hInst, NULL);
but without any success.
also I have used :
#pragma comment(linker, \
"\"/manifestdependency:type='Win32' "\
"name='Microsoft.Windows.Common-Controls' "\
"version='6.0.0.0' "\
"processorArchitecture='*' "\
"publicKeyToken='6595b64144ccf1df' "\
"language='*'\"")
in my code so I removed it to see if tooltip coloring works but the tooltip did not appeared at all !
what is the problem ?
Thanks.
Update 1 :
Here is my full source code , hope to solve the problem :
Main.cpp :
#include <Windows.h>
#include <stdlib.h>
#include <tchar.h>
#include <memory>
#include <malloc.h>
#include "resource.h"
#include <CommCtrl.h>
#include <Uxtheme.h>
HINSTANCE hInst;
BOOL InitInstance(HINSTANCE, int);
INT_PTR CALLBACK MainWin(HWND, UINT, WPARAM, LPARAM);
#pragma comment(linker, \
"\"/manifestdependency:type='Win32' "\
"name='Microsoft.Windows.Common-Controls' "\
"version='6.0.0.0' "\
"processorArchitecture='*' "\
"publicKeyToken='6595b64144ccf1df' "\
"language='*'\"")
#pragma comment(lib, "ComCtl32.lib")
#pragma comment(lib,"UxTheme.lib")
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPTSTR lpCmdLine,_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
while (GetMessage(&msg, NULL, 0, 0)>0)
{
if (!IsDialogMessage(msg.hwnd,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
HWND CreateToolTip(int toolID, HWND hDlg, HINSTANCE hInst, PTSTR pszText)
{
if (!toolID || !hDlg || !pszText)
{
return NULL;
}
HWND hwndTool = GetDlgItem(hDlg, toolID);
if (!hwndTool)
{
return NULL;
}
HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON |TTS_USEVISUALSTYLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hDlg, NULL,
hInst, NULL);
if (!hwndTip)
{
return NULL;
}
TOOLINFO toolInfo = { 0 };
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hwnd = hDlg;
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfo.uId = (UINT_PTR)hwndTool;
toolInfo.lpszText = pszText;
if (!SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo))
{
DestroyWindow(hwndTip);
return NULL;
}
SendMessage(hwndTip, TTM_SETTIPBKCOLOR, 0xFF326FD8, 0);
return hwndTip;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hWnd = CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_MainDlg), NULL, MainWin, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
SetWindowTheme(hWnd, L"", L"");
return TRUE;
}
INT_PTR CALLBACK MainWin(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
{
CreateToolTip(IDC_TestBtn, hDlg, hInst, L"TESTTOOLTIP");
return (INT_PTR)TRUE;
}
break;
case WM_CLOSE:
DestroyWindow(hDlg);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_TestBtn)
{
MessageBox(NULL, L"TEST", L"TEST", MB_OK);
return (INT_PTR)TRUE;
}
}
return (INT_PTR)FALSE;
}
resource.h :
#define IDD_MainDlg 103
#define IDC_TestBtn 104
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 106
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1006
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
resource script for resource.rc :
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_MainDlg, DIALOG
BEGIN
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_MainDlg DIALOGEX 0, 0, 149, 75
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "testbtn",IDC_TestBtn,41,12,57,49
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
Related
I'm working on a pure WinAPI application in C++ and I want to add a toolbar that lives inside/on a rebar control. I can create and add the toolbar but I can't get the rebar to show up (there are no grippers even though I set the RBBS_GRIPPERALWAYS style):
I took the code from the MSDN pages about toolbar/rebar controls and assembled a minimal sample but still no success. Return codes of CreateWindow and SendMessage etc. look okay to me. I also tried the solution of this question but I can't get it working anyways. Any help would be greatly appreciated.. here's the complete source code:
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <CommCtrl.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include "Resource.h"
#pragma comment(lib, "comctl32.lib")
// Enable visual styles
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
// Toolbar defines
#define IDM_NEW 100
#define IDM_OPEN 101
#define IDM_SAVE 102
#define NUM_TBBUTTONS 3
// Global variables
HINSTANCE g_hInst;
HIMAGELIST g_hImageList = NULL;
// Forward declarations
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
HWND CreateSimpleToolbar(HWND hwndParent);
HWND CreateSimpleRebar(HWND hwndParent, HWND hwndToolbar);
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) {
// Initialize common controls.
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
InitCommonControlsEx(&icex);
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_REBARTEST));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_REBARTEST);
wcex.lpszClassName = _T("RebarTest");
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExW(&wcex);
HWND hwndMainWindow = CreateWindowW(_T("RebarTest"), _T("AppTitle"),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
nullptr, nullptr, hInstance, nullptr);
if (!hwndMainWindow)
return FALSE;
ShowWindow(hwndMainWindow, nCmdShow);
UpdateWindow(hwndMainWindow);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
static HWND hwndToolbar, hwndRebar;
switch (message)
{
case WM_CREATE:
{
hwndToolbar = CreateSimpleToolbar(hwnd);
hwndRebar = CreateSimpleRebar(hwnd, hwndToolbar);
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Menüauswahl analysieren:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hwnd);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
HWND CreateSimpleToolbar(HWND hwndParent) {
// Create the toolbar.
HWND hwndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL);
if (hwndToolbar == NULL)
return NULL;
// Create the image list.
g_hImageList = ImageList_Create(16, 16, ILC_COLOR16 | ILC_MASK, NUM_TBBUTTONS, 0);
// Set the image list and add buttons
const int imageListID = 0;
SendMessage(hwndToolbar, TB_SETIMAGELIST, (WPARAM)imageListID, (LPARAM)g_hImageList);
SendMessage(hwndToolbar, TB_LOADIMAGES, (WPARAM)IDB_STD_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
// Initialize button info.
TBBUTTON tbButtons[NUM_TBBUTTONS] =
{
{ MAKELONG(STD_FILENEW, imageListID), IDM_NEW, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"New" },
{ MAKELONG(STD_FILEOPEN, imageListID), IDM_OPEN, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"Open"},
{ MAKELONG(STD_FILESAVE, imageListID), IDM_SAVE, 0, BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"Save"}
};
// Add buttons.
SendMessage(hwndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
SendMessage(hwndToolbar, TB_ADDBUTTONS, (WPARAM)NUM_TBBUTTONS, (LPARAM)&tbButtons);
// Resize the toolbar, and then show it.
SendMessage(hwndToolbar, TB_AUTOSIZE, 0, 0);
ShowWindow(hwndToolbar, TRUE);
return hwndToolbar;
}
HWND CreateSimpleRebar(HWND hwndParent, HWND hwndToolbar) {
// Check parameters.
if (!hwndParent || !hwndToolbar)
return NULL;
// Create the rebar.
HWND hwndRebar = CreateWindowEx(WS_EX_TOOLWINDOW,
REBARCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
RBS_VARHEIGHT | CCS_NODIVIDER | RBS_BANDBORDERS,
0, 0, 0, 0,
hwndParent, NULL, g_hInst, NULL);
if (!hwndRebar)
return NULL;
// Get the height of the toolbar.
DWORD dwBtnSize = (DWORD)SendMessage(hwndToolbar, TB_GETBUTTONSIZE, 0, 0);
REBARBANDINFO rbBand;
rbBand.cbSize = sizeof(REBARBANDINFO);
rbBand.fMask =
RBBIM_STYLE // fStyle is valid.
| RBBIM_TEXT // lpText is valid.
| RBBIM_CHILD // hwndChild is valid.
| RBBIM_CHILDSIZE // child size members are valid.
| RBBIM_SIZE; // cx is valid
rbBand.fStyle = RBBS_CHILDEDGE | RBBS_GRIPPERALWAYS;
rbBand.lpText = (LPWSTR)_T("");
rbBand.hwndChild = hwndToolbar;
rbBand.cyChild = LOWORD(dwBtnSize);
rbBand.cxMinChild = NUM_TBBUTTONS * HIWORD(dwBtnSize);
rbBand.cyMinChild = LOWORD(dwBtnSize);
rbBand.cx = 0; // The default width is the width of the buttons.
// Add the band with the toolbar.
SendMessage(hwndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
return hwndRebar;
}
As described in the comments on this question, you need to have a _WIN32_WINNT defined, which I assume you may have in your "targetver.h" header. Since you are declaring common-controls version 6, I think you need to target WS-2003/Vista at a minimum, according to this. I first tried #define WINVER 0x0601 and #define _WIN32_WINNT_WIN7 0x0601 with your code and it worked on my machine.
I think the question you linked is a little out of date, this table says the structure size for common-controls version 6 should be REBARBANDINFO_V6_SIZE. However, I encountered the 4 pixel height issue from your linked question when using that structure size. Keeping your sizeof code as-is worked for me.
I think the real issue you have is your toolbar is handling its own resizing and positioning. As described on this About Toolbar Control page, you need to change this
HWND hwndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL);
to this
HWND hwndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_WRAPABLE | CCS_NORESIZE | CCS_NOPARENTALIGN, 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL);
in your CreateSimpleToolbar function so the host rebar can take control of the toolbar sizing and positioning.
I want to add columns to a ListView control. You can see what I tried below using ListView_InsertColumn, but I'm getting "identifier x is undefined". It should be in CommCtrl.h, but I don't know what's wrong. I've seen some people using CListView_InsertColumn instead. Not sure what the difference is.
#include <Windows.h>
#include "resource.h"
#pragma comment(linker, "\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#include <CommCtrl.h> // LV_COLUMN and ListView_x
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_INITDIALOG:
LVCOLUMNW col;
col.mask = LVCF_TEXT | LVCF_WIDTH | LVIF_IMAGE;
col.cx = 40;
ListView_InsertColumn(GetDlgItem(hWnd, IDC_LIST2), 0, &col);
return TRUE;
case WM_NCDESTROY:
PostQuitMessage(0);
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
DestroyWindow(hWnd);
break;
default:
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
int WINAPI WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nShowCmd
)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
HWND hWnd = CreateDialogParamW(hInstance, MAKEINTRESOURCEW(IDD_MAIN), nullptr, &DialogProc, 0);
if (!hWnd)
{
MessageBoxW(nullptr, L"Dialog Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);
MSG msg;
while (GetMessageW(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_MAIN, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 169
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_MAIN DIALOGEX 0, 0, 309, 176
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Test"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LISTBOX IDC_LIST2,29,44,235,56,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
END
/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//
IDD_MAIN AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
As mentioned in the comments, the control you define in your resource script is a ListBox, not a ListView. For the latter, you'll need to use the generic CONTROL statement with a control class of "SysListView32" (this can be inserted from the Visual Resource Editor as a "List Control" object, with its "View" property set to "Report"). Note: Without the LVS_REPORT style, you can't add columns to your control.
Here's a suggested replacement for the dialog resource you have:
IDD_MAIN DIALOGEX 0, 0, 309, 176
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Test"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
//LISTBOX IDC_LIST2, 29, 44, 235, 56, LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
CONTROL "", IDC_LIST2, "SysListView32", LVS_REPORT | LVS_SORTASCENDING | WS_VSCROLL | WS_TABSTOP,
29, 44, 235, 56
END
With only that change made, your program will crash/hang during the call to ListView_InsertColumn, because you have specified the LVCF_WIDTH and LVCF_IMAGE flags in the mask member of the LVCOLUMN structure but have not provided valid data for those flags. I can't just 'invent' an image for you but, with some 'dummy' text values (and an extra column, for good measure), here's a suggestion for some 'fixed' code:
switch (Message) {
case WM_INITDIALOG: {
wchar_t c0txt[] = L"abc-0";
LVCOLUMNW col;
col.mask = LVCF_TEXT | LVCF_WIDTH;// | LVIF_IMAGE;
col.cx = 40;
col.pszText = c0txt;
ListView_InsertColumn(GetDlgItem(hWnd, IDC_LIST2), 0, &col);
// Add another column...
wchar_t c1txt[] = L"xyz-1";
col.mask = LVCF_TEXT | LVCF_WIDTH;// | LVIF_IMAGE;
col.cx = 80;
col.pszText = c1txt;
ListView_InsertColumn(GetDlgItem(hWnd, IDC_LIST2), 1, &col);
return TRUE;
}
When building your code with just the changes outlined above, I get a list view control with two columns:
We are trying to create dynamic tool tips where the tool tip changes based on the language the user selected. (C++ win api 64 bit application, no external libraries being used)
However we can't get this to work. The tool tip only ever displays the first letter of the text.
Code snipet:
wchar_t* ws = new wchar_t[200];
swprintf(ws, 200, L"Hello");
TTTOOLINFOW toolInfoW = { 0 };
toolInfoW.cbSize = sizeof(toolInfoW);
toolInfoW.hwnd = hDlg;
toolInfoW.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfoW.uId = (UINT_PTR)hwndTool;
toolInfoW.lpszText = ws;
Even if we hard code the 'Hello', only the first letter is displayed
TTTOOLINFOW toolInfoW = { 0 };
toolInfoW.cbSize = sizeof(toolInfoW);
toolInfoW.hwnd = hDlg;
toolInfoW.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfoW.uId = (UINT_PTR)hwndTool;
toolInfoW.lpszText = L"Hello";
We must be missing something extremely obvious because it can't be this hard to get this to work.
Thanks in advance for any advice.
Out of curiosity, I've tried it out, and the following code did work when compiled for x64 using MSVC 2019 on Windows 10. It creates a simple window with a button in it, and when you hover over that button, it displays a tooltip with text This works! ☺ (containing a smiley face Unicode character).
Be sure to compile this example with C++17 enabled, otherwise the buffer returned by data() will have type const wchar_t* and thus will be incompatible with the lpszText (member of the TTTOOLINFOW structure), which has type LPWSTR, i.e. just wchar_t*.
#pragma comment(linker, "\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' \
language='*'\"")
#pragma comment(lib, "comctl32.lib")
#define _WIN32_WINNT _WIN32_WINNT_WIN10
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#include <SDKDDKVer.h>
#include <windows.h>
#include <commctrl.h>
#include <string>
HINSTANCE g_hInstance{ nullptr };
HWND CreateMyButton(HINSTANCE hInstance, HWND hWndApp)
{
return ::CreateWindowExW(0UL, L"BUTTON", L"Hover over this button",
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 45, 10, 200, 35,
hWndApp, nullptr, hInstance, nullptr);
}
void CreateMyTooltip(HWND hWndParent, HWND hWndControl)
{
HWND hWndTip{ ::CreateWindowExW(WS_EX_TOPMOST, TOOLTIPS_CLASSW,
nullptr, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, 0, 0, 0, 0,
hWndParent, nullptr, nullptr, nullptr) };
::SetWindowPos(hWndTip, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
std::wstring wsTooltipText{ L"This works! \u263A" };
TTTOOLINFOW ti{};
ti.cbSize = sizeof ti;
ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
ti.hwnd = hWndParent;
ti.uId = reinterpret_cast<UINT_PTR>(hWndControl);
ti.lpszText = wsTooltipText.data();
::SendMessageW(hWndTip, TTM_ADDTOOL, 0U, reinterpret_cast<LPARAM>(&ti));
}
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
CreateMyTooltip(hWnd, CreateMyButton(g_hInstance, hWnd));
break;
case WM_DESTROY:
::PostQuitMessage(0);
break;
default:
break;
}
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
}
int WINAPI wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE, _In_ LPWSTR, _In_ int)
{
g_hInstance = hInstance;
const INITCOMMONCONTROLSEX initControls
{
sizeof(INITCOMMONCONTROLSEX),
ICC_STANDARD_CLASSES | ICC_WIN95_CLASSES
};
::InitCommonControlsEx(&initControls);
WNDCLASSW wc{};
wc.lpfnWndProc = MyWndProc;
wc.hInstance = hInstance;
wc.hCursor = ::LoadCursorW(nullptr, IDC_ARROW);
wc.hbrBackground = ::GetSysColorBrush(COLOR_3DFACE);
wc.lpszClassName = L"Tooltip";
::RegisterClassW(&wc);
::CreateWindowExW(0UL, wc.lpszClassName, L"Tooltip Example",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
300, 100, nullptr, nullptr, hInstance, nullptr);
MSG msg{};
while (::GetMessageW(&msg, nullptr, 0U, 0U))
{
::TranslateMessage(&msg);
::DispatchMessageW(&msg);
}
return static_cast<int>(msg.wParam);
}
This question already has an answer here:
Is it possible to create a winapi window with only borders
(1 answer)
Closed 2 years ago.
I am dealing with win32. I have created a window. What I want is a transparent window for clicked area but nontransparent for border. Additionaly with no title bar. It should seem like an empty rectangle. When I add the following code I, my whole window becomes transparent (borders are also tranparent.)
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 75, LWA_ALPHA);
SetWindowLong(hwnd, GWL_STYLE, 0);
The output of my code by adding the above code is like following:
When opacity value is 255:
When opacity value is 75
As you can see that the borders also transparent. How can I prevent becoming transparent border, but obtain transparent clicked area like a rectange?
Thanks...
It looks like you want to make part of the window transparent.For this, you need to create two windows to complete.
Use SetWindowRgn to create a window with a hole
Use the WS_EX_LAYERED and WS_EX_TRANSPARENT style to place
another transparent window in the hole.
Like this:
The whole code:
// Test_transparent.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "Test_transparent.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
HWND hWnd;
HWND child;
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_TESTTRANSPARENT, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTTRANSPARENT));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TESTTRANSPARENT));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TESTTRANSPARENT);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hWnd = CreateWindowEx(0, szWindowClass, L" ", WS_POPUP, 100, 100, 800, 600, NULL, NULL, hInst, 0);
child = CreateWindowEx(WS_EX_LAYERED, szWindowClass, szTitle, WS_POPUP | WS_VISIBLE | WS_CHILD, 300, 300, 200, 200, hWnd, NULL, hInst, 0);
SetLayeredWindowAttributes(child, 0, 50, LWA_ALPHA);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
RECT rect;
RECT rc;
COLORREF brColor;
static HRGN hRgnWnd;
static HRGN hRgnWnd1;
static HBRUSH hBr;
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
brColor = RGB(51, 143, 178);
hBr = CreateSolidBrush(brColor);
GetClientRect(hWnd, &rect);
rc.left = 200;
rc.top = 200;
rc.right = 400;
rc.bottom = 400;
hRgnWnd = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
hRgnWnd1 = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
CombineRgn(hRgnWnd1, hRgnWnd1, hRgnWnd, RGN_XOR);
SetWindowRgn(hWnd, hRgnWnd1, true);
FillRect(hdc, &rect, hBr);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
To get a borderless window, you need to comment the MENU code in the .rc file.
.rc cpp
//Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE resource.
//
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_TESTTRANSPARENT ICON "Test_transparent.ico"
IDI_SMALL ICON "small.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
//
//IDC_TESTTRANSPARENT MENU
//BEGIN
// POPUP "&File"
// BEGIN
// MENUITEM "E&xit", IDM_EXIT
// END
// POPUP "&Help"
// BEGIN
// MENUITEM "&About ...", IDM_ABOUT
// END
//END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDC_TESTTRANSPARENT ACCELERATORS
BEGIN
"?", IDM_ABOUT, ASCII, ALT
"/", IDM_ABOUT, ASCII, ALT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Test_transparent"
FONT 8, "MS Shell Dlg"
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20
LTEXT "Test_transparent, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
LTEXT "Copyright (c) 2020",IDC_STATIC,42,26,114,8
DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 163
TOPMARGIN, 7
BOTTOMMARGIN, 55
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#ifndef APSTUDIO_INVOKED\r\n"
"#include ""targetver.h""\r\n"
"#endif\r\n"
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDC_TESTTRANSPARENT "TESTTRANSPARENT"
IDS_APP_TITLE "Test_transparent"
END
#endif
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
Is there any way to get the current progress of a timer, which is created by the SetTimer function?
Here's an implementation of Hans' comment. Clicking the button shows the time remaining until the next scheduled (expected) WM_TIMER message. By building in debug mode, I get a console to display my messages, since it's such a quick and easy (read: dirty) way of getting both a GUI and a console.
main.cpp
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"
HINSTANCE hInst;
DWORD tickCountInitial;
DWORD timerInterval = 10000;
DWORD nextTimerFired;
BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
tickCountInitial = GetTickCount();
SetTimer(hwndDlg, 666, timerInterval, NULL);
nextTimerFired = tickCountInitial + timerInterval;
}
return TRUE;
case WM_TIMER:
{
DWORD tickCountCurrent = GetTickCount();
printf("Ticks elapsed: %d\n", tickCountCurrent - tickCountInitial);
nextTimerFired = tickCountCurrent + timerInterval;
MessageBeep(MB_OK);
}
return 0;
case WM_CLOSE:
{
EndDialog(hwndDlg, 0);
}
return TRUE;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
{
DWORD tickCountCurrent = GetTickCount();
printf("Ticks till next WM_TIMER message: %d\n", nextTimerFired - tickCountCurrent);
}
break;
}
}
return TRUE;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hInst=hInstance;
InitCommonControls();
return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
}
resource.h
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define DLG_MAIN 100
#define IDC_BUTTON1 40000
resource.rc
// Generated by ResEdit 1.6.2
// Copyright (C) 2006-2014
// http://www.resedit.net
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"
//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
DLG_MAIN DIALOG 0, 0, 186, 95
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "Ms Shell Dlg"
{
PUSHBUTTON "Check Remaining", IDC_BUTTON1, 41, 32, 104, 31, 0, WS_EX_LEFT
}
//
// Manifest resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
1 RT_MANIFEST ".\\manifest.xml"