C++ Tooltip function for checkbox - c++

actually, my aim is to set a Tool tip for a checkbox function though, it doesn't seem to work. :/
the checkboxes are managed in a resource file using the format, BS_AUTOSTATE for every one of them. though I thought of initializing a tooltip for those checkboxes and a certain friend had suggested to use the following method,
text = dialog_message(IDC_FILE);
SetWindowText(GetDlgItem(m_hWnd, IDC_FILE), text));
and unfortunately, it didn't work. anyone has any other ideas for implementing tooltip without any other dependencies.

From #andlab's link: How to Create a Tooltip for a Control or a rectangular area:
Using Tooltip Controls
Tooltip requires common control version 4.70 or higher. Make sure project manifest is setup correctly.
You can use the CreateToolTip function below:
CreateToolTip(hWnd, hWndDialogItem, L"TESTING");
Example for a dialog box:
#include "windows.h"
#include "resource.h"
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
void CreateToolTip(
HWND hWndParent, /*HWND handle for the parent window, for example dialog box*/
HWND hControlItem, /*HWND handle for the control item, for example checkbox*/
PTSTR pszText /*text for the tool-tip*/)
{
if (!hControlItem || !hWndParent || !pszText)
return;
// Create the tooltip. g_hInst is the global instance handle.
HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP /* | TTS_BALLOON*/,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hWndParent, NULL, GetModuleHandle(0), NULL);
if (!hwndTip)
return;
// Associate the tooltip with the tool.
TOOLINFO toolInfo = { 0 };
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hwnd = hWndParent;
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfo.uId = (UINT_PTR)hControlItem;
toolInfo.lpszText = pszText;
if (!SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo))
{
//OutputDebugString(L"TTM_ADDTOOL failed\nWrong project manifest!");
MessageBox(0, TEXT("TTM_ADDTOOL failed\nWrong project manifest!"), 0, 0);
}
}
BOOL CALLBACK DialogProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_INITDIALOG:
{
HWND hDlgItem = GetDlgItem(hDlg, IDOK);
if (hDlgItem)
{
CreateToolTip(hDlg, hDlgItem, L"TESTING");
}
else
{
MessageBox(0, TEXT("Cannot find dialog item with IDOK identifier"), 0, 0);
}
break;
}
case WM_COMMAND:
switch (wp)
{
case IDOK:
EndDialog(hDlg, wp);
break;
case IDCANCEL:
EndDialog(hDlg, wp);
break;
}
}
return FALSE;
}
int APIENTRY wWinMain(HINSTANCE hinst, HINSTANCE, LPTSTR, int nCmdShow)
{
DialogBox(hinst, MAKEINTRESOURCE(IDD_DIALOG1), 0, DialogProc);
return 0;
}

Related

win32 GUI not loading properly after adding an edit window

When I build the program in visual studio It takes a long time to build and does not display properly, during this proccess it loads and unloads lots of what appears to be dll files in the console. If I remove the one line that starts with CreateWindowW(L"EDIT" the program will run perfectly. I have read through the documentation and I cant find what is wrong with it. Any help is appreciated.
Here is full code
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include<iostream>
#define file_menu_new 1
#define help_menu 2
#define file_menu_open 3
#define file_menu_exit 4
void AddMenus(HWND hwind);
HMENU hMenu;
void AddControls(HWND hwnd);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,_In_ PSTR szCmdLine, _In_ int iCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
//regesters class above with operateing system
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW | WS_VISIBLE, // Window style
// Size and position
500, 200, 800, 500,//WS_DEFAULT OR SOMETHING LIKE THAT
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, iCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
{
switch (wParam)
{
case file_menu_new:
MessageBeep(MB_OK);//this creates a sound
break;
case file_menu_exit:
DestroyWindow(hwnd);
break;
case file_menu_open:
MessageBeep(MB_ICONINFORMATION);
default:
break;
}
}
case WM_CREATE:
{
AddControls(hwnd);
AddMenus(hwnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
break;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void AddMenus(HWND hwind)
{
hMenu = CreateMenu();//main menu bar
HMENU hFileMenu = CreateMenu();//this is a drop down menu for the file part of main menu
//AppendMenu(hMenu, MF_STRING, 1, L"File");//1 is the identity of this main menu
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"File");//this is how you make it pop up another menu
AppendMenu(hFileMenu, MF_STRING, file_menu_new, L"New");//adds stuff to hFileMenu with the id of 1
AppendMenu(hFileMenu, MF_STRING, file_menu_open, L"Open");//adds stuff to hFileMenu with the id of 3
AppendMenu(hFileMenu, IMFT_SEPARATOR, NULL, NULL);//creates a seperator or a line under open
AppendMenu(hFileMenu, MF_STRING, file_menu_exit, L"Exit");
AppendMenu(hMenu, MF_STRING, help_menu, L"Help");//2 is the identity of this main menu
//sets the hMenu to the hwind menu or the main menu
SetMenu(hwind, hMenu);
}
void AddControls(HWND hwnd)
{
CreateWindowW(L"static", L"Enter Text here: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER | WS_EX_TRANSPARENT,
200, 100, 100, 50, hwnd, NULL, NULL, NULL);
CreateWindowW(L"EDIT", L"Enter Text here: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER,
200, 160, 100, 50, hwnd, NULL, NULL, NULL);
}
Add wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); and remove WM_PAINT. If you don't set a class background you need to handle WM_ERASEBKGND or otherwise validate the background color painting.

Close popup menu programmatically on Windows

I have a simple example for creating popup menu. I want to close this menu programmatically when pressing on button, is there any possibility to do that? Or maybe I should use different class?
I need to open this menu when button is pressed and close it the same way when pressing the button. Here is simple code example that I have.
#define MAX_LOADSTRING 100
#define IDM_FILE_NEW 1
#define IDM_FILE_OPEN 2
#define IDM_FILE_QUIT 3
#define BUTTON_ID 1
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
HWND gButton = NULL;
HWND mainHwnd = NULL;
HMENU hMenu;
bool gMenuHidden = false;
// 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);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_POPUPMENU, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_POPUPMENU));
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;
}
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_POPUPMENU));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
mainHwnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!mainHwnd)
{
return FALSE;
}
ShowWindow(mainHwnd, nCmdShow);
UpdateWindow(mainHwnd);
return TRUE;
}
HMENU CreateAndInitializeMenu()
{
HMENU menu = CreatePopupMenu();
AppendMenuW(menu, MF_STRING, IDM_FILE_NEW, L"&New");
AppendMenuW(menu, MF_STRING, IDM_FILE_OPEN, L"&Open");
AppendMenuW(menu, MF_SEPARATOR, 0, NULL);
AppendMenuW(menu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
return menu;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_COMMAND:
{
if (wParam == BUTTON_ID)
{
//gMenuHidden = !gMenuHidden;
if (gMenuHidden)
{
hMenu = CreateAndInitializeMenu();
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, 150, 250, 0, mainHwnd, NULL);
DestroyMenu(hMenu);
}
else
{
// TODO:
}
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
{
gButton = CreateWindowW(L"button", L"Show/Hide menu", WS_VISIBLE | WS_CHILD, 100, 120, 120, 25, hWnd, (HMENU)BUTTON_ID, NULL, NULL);
break;
}
}
return DefWindowProcW(hWnd, message, wParam, lParam);
}
Maybe the right way is to always create menu when button is pressed and destroy it right after that? But in that case we should create menu all the time when pressing the button. I was trying to create the menu once and show it when we need it. Also the menu is not shown right now. Trying to figure out why.
Thanks in advance.
First, you can certainly avoid repeating the creation/destruction of your popup menu: just create it (once) on window creation (by handling the WM_CREATE message) and destroy it when handling WM_DESTROY. But note: you will need to make your hMenu a static variable, so that its value is maintained across multiple calls of your WndProc function.
As for hiding the menu programmatically – you can do this by sending the parent window the WM_CANCELMODE message, as suggested in this related question: How to CLOSE a context menu after a timeout?
You can keep a 'flag' variable (also must be static) to keep track of the current display status of the popup menu: if this is not shown, call TrackPopupMenu; if it is shown, send the WM_CANCELMODE message. You will also need to add the TPM_RETURNCMD flag in your call to TrackPopupMenu, so that you can reset the flag if/when the user selects a command from the menu.
Here's a version of your WndProc function that implements this approach:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HMENU hMenu; // Make "static" so we can reuse across calls
static bool hasMenu = false; // Flag to indicate current menu status
POINT point;
switch (msg) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_FILE_NEW:
case IDM_FILE_OPEN:
MessageBeep(MB_ICONINFORMATION);
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_CREATE:
// Create the menu (once only) on window creation...
hMenu = CreatePopupMenu();
AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW, L"&New");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN, L"&Open");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
hasMenu = false; // Reset here in case of multiple uses.
break;
case WM_RBUTTONUP:
if (!hasMenu) { // Only show menu if it's not already active...
hasMenu = true;
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
ClientToScreen(hwnd, &point);
// Add the "TPM_RETURNCMD" flag so we can reset "hasMenu" when a command is sselected (return non-zero):
BOOL cmd = TrackPopupMenu(hMenu, TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, 0, hwnd, NULL);
if (cmd) {
hasMenu = false;
SendMessage(hwnd, WM_COMMAND, cmd, 0); // Send the command (not done automatically with TPM_RETURNCMD)
}
}
else {
hasMenu = false;
SendMessage(hwnd, WM_CANCELMODE, 0, 0);
}
break;
case WM_DESTROY:
DestroyMenu(hMenu); // Destroy the menu.
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}

Listview C++ win32 API - Example Not Working

I am trying to create a listview in C++ with the win32 api, however the code supplied on mdsn is giving me an error.
HWND CreateListView (HWND hwndParent)
{
INITCOMMONCONTROLSEX icex; // Structure for control initialization.
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
RECT rcClient; // The parent window's client area.
GetClientRect (hwndParent, &rcClient);
// Create the list-view window in report view with label editing enabled.
HWND hWndListView = CreateWindow(WC_LISTVIEW, //ERROR red line under create window
L"",
WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
0, 0,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
hwndParent,
(HMENU)IDM_CODE_SAMPLES, //ERROR IDM CODE SAMPLES undefined
g_hInst, //ERROR
NULL);
return (hWndListView);
}
This example is strait from mdsn and I have no idea why it is not working. I am getting IDM_CODE_SAMPLES Undefined, and something wrong with createwindow. Please help me to get this working it would be really helpful.
IDM_CODE_SAMPLES is the ID you want to assign to your control. You can either define the symbol to a numeric value, or use the numeric value directly (choose 100, for example). The ID is useful if you want to reference a particular control, although its HWND is equally useful as an ID.
g_hInst is presumably a global variable of type HMODULE, initialized from WinMain. If you don't want to use the global variable, you can call GetModuleHandle(nullptr) in its place, provided that you are compiling an .exe as opposed to a .dll.
You'll get a lot of helpful information when working through Intro to Win32 programming in C++.
I am now getting an error (1 unresolved externals)
We can find from InitCommonControlsEx function.
Ensures that the common control DLL (Comctl32.dll) is loaded, and
registers specific common control classes from the DLL.
Add:
#include <commctrl.h>
#pragma comment(lib,"Comctl32.lib")
Minimal code example:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib,"Comctl32.lib")
#define IDM_CODE_SAMPLES 101
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND CreateListView(HWND hwndParent);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
CreateListView(hwnd);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
HWND CreateListView(HWND hwndParent)
{
INITCOMMONCONTROLSEX icex; // Structure for control initialization.
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
RECT rcClient; // The parent window's client area.
GetClientRect(hwndParent, &rcClient);
// Create the list-view window in report view with label editing enabled.
HWND hWndListView = CreateWindow(WC_LISTVIEW, //ERROR red line under create window
L"",
WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
0, 0,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
hwndParent,
(HMENU)IDM_CODE_SAMPLES, //ERROR IDM CODE SAMPLES undefined
GetModuleHandle(nullptr), //ERROR
NULL);
return (hWndListView);
}
Just in case someone else is having issues around SysListView32:
#include <Ole2.h>
OleInitialize(NULL);
#include <commctrl.h>
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "comctl32.lib")
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
BOOL bRet = InitCommonControlsEx(&InitCtrls);
...
For reference: fully working example with bells and whistles: https://github.com/jjYBdx4IL/Win32-List-View

Win32 Combobox, print the name of selected to edit text box

I am testing out a thoery for the Combobox for win32. Many things have been tried but I am not understanding how to make it do what I want it to do. When the selection is made in the combo box I want it to print into the edit box. I believe this would be done through the handle maybe.
So if I add it to my button 1 through a cast for button 1 how do you get it to print out to the edit field??
My code is below. I left in some of the things I tried but commented it out. The problem is in add controls and I am thinking my switch and case.
I am missing that one part that populate the text to the edit box.
I am not so much new to programming so much as new to this type of programming. I am looking for a simple approach. Thanks in advance for your time.
Below is the updated code and what I got for now. I followed the guidelines for unicode. I even made friends with visual studio c++(I think).
#include <windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
#define OPTINBT1 1
#define OPTINBT2 2
#define COMBO1 3
HWND hWnd, hComboOne;
void addControl(HWND);
LPCWSTR egClassName = L"myWindowClass";
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int nCmdShow)
{
WNDCLASSW wc = { 0 };
wc.lpszClassName = egClassName;
wc.lpfnWndProc = WindowProcedure;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hInstance = hInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClassW(&wc))
{
const wchar_t Error01[] = L"Register Issue To Check On : ";
const wchar_t Error01_Caption[] = L"Error 01";
MessageBoxW(hWnd, Error01, Error01_Caption, MB_OK | MB_ICONERROR);
return 0;
}
LPCWSTR parentWinTitle = L"My Window";
hWnd = CreateWindowW(egClassName, parentWinTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 500, 500, NULL, NULL, NULL, NULL);
if (hWnd == NULL)
{
const wchar_t Error02[] = L"Window Creation Issue To Check On : ";
const wchar_t Error02_Caption[] = L"Window Creation Issue To Check On : ";
MessageBoxW(hWnd, Error02, Error02_Caption, MB_OK | MB_ICONERROR);
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_CREATE:
addControl(hWnd);
break;
case WM_COMMAND:
if (HIWORD(wp) == CBN_SELCHANGE)
{
if (LOWORD(wp) == COMBO1)
{
HWND hcombo = (HWND)lp;
LRESULT index = SendMessageW(hcombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
wchar_t buf[256];
SendMessageW(hcombo, (UINT)CB_GETLBTEXT, (WPARAM)index, (LPARAM)buf);
MessageBoxW(hWnd, buf, L"Good Example", 0);
}
break;
}
switch (LOWORD(wp))
{
case OPTINBT1:
MessageBoxW(hWnd, L"This is Radio button1: ", L"Radio Button 2 is good", MB_OK);
break;
case OPTINBT2:
MessageBoxW(hWnd, L"This is Radio button2: ", L"Radio Button 1 is good", MB_OK);
break;
default:break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, msg, wp, lp);
}
return 0;
}
void addControl(HWND hWnd)
{
HWND OptBt1, OptBt2;
const LPCWSTR cont1 = L"STATIC";
const LPCWSTR cont2 = L"COMBOBOX";
const LPCWSTR cont3 = L"BUTTON";
const LPCWSTR emptyS = L"";
const LPCWSTR bl = L"RButton 1";
const LPCWSTR b2 = L"RButton 2";
//Option buttons
OptBt1 = CreateWindowW(cont3, bl, WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, 24, 8, 90, 25, hWnd, (HMENU)OPTINBT1, NULL, NULL);
OptBt2 = CreateWindowW(cont3, b2, WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, 24, 40, 90, 25, hWnd, (HMENU)OPTINBT2, NULL, NULL);
SendMessage(OptBt1, BM_SETCHECK, BST_CHECKED, 0);
hComboOne = CreateWindowW(cont2, emptyS, WS_VISIBLE | WS_CHILD | CBS_DROPDOWN | CBS_HASSTRINGS | WS_VSCROLL, 77, 70, 150, 150, hWnd, (HMENU)COMBO1, 0, 0);
LPCWSTR ComboBoxItems[] = { L"Subject1", L"Subject2", L"Subject3",
L"Subject4", L"Subject5" };
/** Or the array way */
SendMessageW(hComboOne, CB_ADDSTRING, 0, (LPARAM)ComboBoxItems[0]);
SendMessageW(hComboOne, CB_ADDSTRING, 0, (LPARAM)ComboBoxItems[1]);
SendMessageW(hComboOne, CB_ADDSTRING, 0, (LPARAM)ComboBoxItems[2]);
SendMessageW(hComboOne, CB_ADDSTRING, 0, (LPARAM)ComboBoxItems[3]);
SendMessageW(hComboOne, CB_ADDSTRING, 0, (LPARAM)ComboBoxItems[4]);
}
WM_CREATE should be inserted before addControl.
In WM_COMMAND respond to CBN_SELCHANGE notification to detect combobox selection change.
When you show a message box you can use the handle of your own window MessageBox(hWnd,...). If you supply NULL as the handle then the message box becomes the child of desktop window, it behaves as if it is displayed in modeless mode.
switch(msg)
{
case WM_CREATE:
addControl(hWnd);
break;
case WM_COMMAND:
if(HIWORD(wp) == CBN_SELCHANGE)
{
if(LOWORD(wp) == COMBO1)
{
HWND hcombo = (HWND)lp;
int index = SendMessage(hcombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
char buf[256];
SendMessage(hcombo, (UINT)CB_GETLBTEXT, (WPARAM)index, (LPARAM)buf);
MessageBox(hWnd, buf, 0, 0);
}
break;
}
switch(LOWORD(wp))
{
case OPTINBT1:
MessageBox(hWnd, "This is Radio button1: ", "ComboBox Working??", MB_OK);
break;
case OPTINBT2:
MessageBox(hWnd, "This is Radio button2: ", "ComboBox Working??", MB_OK);
break;
default:break;
}
break;
Not related to your problem, but you are mixing Unicode (example L"EDIT") with ANSI (example "EDIT").
Window functions like CreateWindow are macros. In ANSI it is CreateWindowA, and in Unicode it is the wide function CreateWindowW
You are compiling your program in old ANSI mode. CreateWindow is a macro to CreateWindowA which needs ANSI input. CreateWindow("EDIT",...)
If you compile your program in Unicode, CreateWindow is a macro for the wide function CreateWindowW which uses Unicode parameter CreateWindow(L"EDIT",...)
If you create a project in Visual Studio it will default to the new Unicode standard. Use wide char (L"Text") and Unicode functions everywhere. I would recommend compiling the program with warning level 4. Make sure the program compiles with zero warnings.
You want to respond to the CBN_SELCHANGE message that is sent to your window procedure. In the case of WM_COMMAND the low word of wParam will contain the control ID, the high word will contain an optional command code.
That command code is critical for properly responding to combo box messages. You will want to respond to the CBN_SELCHANGE message by sending the combo box a CB_GETCURSEL and then CB_GETLBTEXTLEN and CB_GETLBTEXT, after that you can send your edit control a WM_SETTEXT with the retrieved text.

win32 c++ handle button press, PeekMessage not working?

I want to handle a c++ win32 API button press in a native window, I'm currently attempting doing it like so -
#include <stdint.h>
#include <Windows.h>
#include <process.h>
#include <iostream>
#include <sstream>
#include <tchar.h>
#include <strsafe.h>
#include <crtdefs.h>
#include <stdafx.h>
#include <stdio.h>
#include "stdafx.h"
#include "name.h"
#include "libobs/obs.h"
#include "libobs/obs-module.h"
#define uploadName "Upload Window"
#define uploadWNDWidth 500
#define uploadWNDHeight 500
#define IDC_SELECT_VIDEO (100)
HWND hBtnParent = HWND("UploadVideo");
HWND SelectVideoBTN, UploadBTN, hWnd, hBtn;
WPARAM wmId, wmEvent;
HINSTANCE hUpload;
WNDCLASSEX wcexUpload;
int nCmdShowUpload = 1;
using namespace std;
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
//load obs modules
class load{
public:
void static loading(){
obs_module_load;
obs_module_load_locale;
}
};
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case BM_CLICK:
if (wParam == IDC_SELECT_VIDEO) {
MessageBox(hWnd, L"if", L"if", 0);
}
else{
MessageBox(hWnd, L"else", L"else", 0);
}
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
bool obs_module_load(void)
{
//init handler
//HANDLE messageLoopThreadHandler;
//set the handler to the thread
//messageLoopThreadHandler = (HANDLE)_beginthreadex(0, 0, &messageLoopThread, 0, 0, 0);
//wait for object to be in specified state
//WaitForSingleObject(messageLoopThreadHandler, INFINITE);
//startMessageThreadLoop ThreadLoopInstance;
//ThreadLoopInstance.startMyThread();
MessageBox(hWnd, L"ThreadStart", L"ThreadStart", 0);
//create message loop for buttons
//cleanup thread created by _beginThreadEx
//CloseHandle(messageLoopThreadHandler);
WNDCLASSEX vidUploader;
vidUploader.cbSize = sizeof(WNDCLASSEX);
vidUploader.style = CS_HREDRAW | CS_VREDRAW;
vidUploader.lpfnWndProc = WndProc;
vidUploader.cbClsExtra = 0;
vidUploader.cbWndExtra = 0;
vidUploader.hInstance = hUpload;
vidUploader.hIcon = LoadIcon(hUpload, MAKEINTRESOURCE(IDI_P2GOVIDEOUPLOADER20));
vidUploader.hCursor = LoadCursor(NULL, IDC_ARROW);
vidUploader.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
vidUploader.lpszMenuName = MAKEINTRESOURCE(IDC_P2GOVIDEOUPLOADER20);
vidUploader.lpszClassName = (LPCWSTR)(L"UploadVideo");
vidUploader.hIconSm = LoadIcon(wcexUpload.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassEx(&vidUploader);
hInst = hUpload; // Store instance handle in our global variable
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application dows not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
hWnd = CreateWindow((LPCWSTR)(L"UploadVideo"), (LPCWSTR)(L"Upload Video's"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hUpload, NULL);
SelectVideoBTN = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
L"Select Video's", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
10, // x position
460, // y position
100, // Button width
25, // Button height
hWnd, // Parent window
(HMENU)IDC_SELECT_VIDEO, // Assign appropriate control ID
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
UploadBTN = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
L"Upload", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
390, // x position
460, // y position
100, // Button width
25, // Button height
hWnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
RECT rect = { 0, 0, uploadWNDWidth, uploadWNDHeight };
AdjustWindowRect(&rect, GetWindowLong(hWnd, GWL_STYLE), FALSE);
SetWindowPos(hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE);
if (!hWnd)
{
MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Win32 Guided Tour"), NULL);
return 1;
}
MSG msge = { 0 };
while (PeekMessage(&msge, NULL, 0, 0, PM_REMOVE) > 0)
{
//translate and send messages
TranslateMessage(&msge);
DispatchMessage(&msge);
}
MSG msg;
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
//nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd, nCmdShowUpload);
UpdateWindow(hWnd);
load::loading();
return true;
}
When I currently load OBS, after having included the dll what happens is -
OBS starts
Window pops u
I click on window
Nothing happens
where on step 4, right after clicking on the button a MessageBox should popup saying - MessageBox(hWnd, L"else", L"else", 0); if it goes into the else, and if the if statement is true then MessageBox(hWnd, L"if", L"if", 0);
However my code won't even enter the callback function.
edit -
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
load::loading();
// 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:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
This is where the WndProc references refer to.
You're handling the receive of the button click incorrect. You should handle a WM_COMMAND message and check the high word of the WPARAM for the notification code.
You should use GetMessage, it won't hang the program.
You can use PeekMessage if you want constant update. For example in a game where you need to constantly paint the window. It has to be something like this:
//create window...
//show window...
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
//default message processing
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//constantly paint the window when there is no other message
render_window(hwnd);
}
}
//do cleanup here
return 0;
Note that the program terminates when the above while loop is finished. You cannot put ShowWindow/UpdateWindow after that.
Second, your main window seems to be vidUploader. And the window procedure for it is set to vidUploader.lpfnWndProc = WndProc; But you have not defined WndProc. Instead you have something else called WindowProcedure
To check for button notification:
case WM_COMMAND:
if (LOWORD(wParam) == IDC_SELECT_VIDEO)
MessageBox...;
break;