Reputation: 165
=================================SOLVED=================================
As Ken White mentioned in the comments. I found here a code that helped me. I've edited the code a in some places to adjust it to Visual Studio 2019:
#include <iostream>
#include <Windows.h>
// FUNCTION PROTOTYPES =========================================================
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// entry point for a Windows application =======================================
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmdLine, int nWinMode) {
// define some variables
const wchar_t szWinName[] = L"Win32App";
const wchar_t szAppTitle[] = L"Win32 API Skeletal Application";
HWND hwnd;
MSG msg;
WNDCLASS wc;
// define a window class
wc.hInstance = hInstance; // handle to this instance
wc.lpszClassName = szWinName; // window class name
wc.lpfnWndProc = WndProc; // pointer to window proc
wc.style = 0; // default style
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // predefined icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // predefined cursor
wc.lpszMenuName = NULL; // no class menu
wc.cbClsExtra = 0; // no extra info needed
wc.cbWndExtra = 0; // no extra info needed
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // predefined color brush
// register the defined window class
if (RegisterClass(&wc) == 0)
{
// an error occurred, abort the program
MessageBox(NULL, L"Couldn't Register the Window Class!", L"ERROR", MB_OK | MB_ICONERROR);
return 0;
}
// now that a window class has been registered, create the main window
hwnd = CreateWindow(szWinName, // name of window class to create
szAppTitle, // window title bar caption
WS_OVERLAPPEDWINDOW, // window style - normal
CW_USEDEFAULT, // X coordinate - let Windows decide
CW_USEDEFAULT, // Y coordinate - let Windows decide
CW_USEDEFAULT, // width - let Windows decide
CW_USEDEFAULT, // height - let Windows decide
NULL, // no parent window
NULL, // no menu
hInstance, // handle to this instance
NULL); // no additional arguments
// check to see if window was successfully created
if (hwnd == NULL)
{
// an error occurred, abort
MessageBox(NULL, L"Couldn't Create the Main Window!", L"ERROR", MB_OK | MB_ICONERROR);
return 0;
}
// display (and update) the newly created window
ShowWindow(hwnd, nWinMode);
UpdateWindow(hwnd);
// create the message loop
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg); // translate keyboard messages
DispatchMessage(&msg); // return control to Windows
}
return msg.wParam;
}
// processes the messages that Windows sends to the application ================
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// choose which Windows messages you want to use
switch (message)
{
// the window is being destroyed, so terminate the application
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
// let Windows process any messages not specified in the switch statement
return DefWindowProc(hwnd, message, wParam, lParam);
}
Problem Description: Create new window using Visual Studio 2019 in C++
I'm writing user interface for USB device using Visual Studio 2019, in a console app type of project in cpp. I want to add two features - I want to create buttons which will appear on the screen and will enable the user to:
For example, to store data from an endpoint buffer into a file, the user will click on "store data" and will navigate to the desired file\location. after the location has been chosen, libusb functions will read from the endpoint and will store the data in a temporary struct, from which I will write it into the file.
The main problem for me is to create those buttons and make them display the file explorer. I've started with some short code to create a new window, as written in this guide:
the problem is, when I run the program the window opens and collapses immediately. in addition, I cannot find what functions can help me to make the pressing on a button to open the file explorer.
I'm using windows.h header to create the window. this is my code:
''''
#include <Windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return
DefWindowProc(hwnd, uMsg, wParam, lParam); }
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 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);
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
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
return 0;
}
''''
I added in the linker's additional dependencies the flag "user32.lib" and I also don't have any linker errors, so I guess that's not it. What could be the problem? I've tried looking at other similar questions, but couldn't find anything helpful. also, is there any library which provides functions to open the file explorer after clicking on the button?
I hope my question hasn't been asked before, and is written properly. If there's something wrong with it, please let me know so I can edit it.
Thank you very much for your time and attention.
Upvotes: 0
Views: 689
Reputation: 3890
The reason you run the program the window opens and collapses immediately is that you did not create a message loop. The message loop is not just the WindowProc
function you mentioned. You also need to add a message processing loop function.
According to the MSDN document:
wWinMain is the program entry point. When the program starts, it registers some information about the behavior of the application window. One of the most important items is the address of a function, named WindowProc in this example. This function defines the behavior of the window—its appearance, how it interacts with the user, and so forth.
Next, the program creates the window and receives a handle that uniquely identifies the window.
If the window is created successfully, the program enters a while loop. The program remains in this loop until the user closes the window and exits the application.
Notice that the program does not explicitly call the WindowProc function, even though we said this is where most of the application logic is defined. Windows communicates with your program by passing it a series of messages. The code inside the while loop drives this process. Each time the program calls the
DispatchMessage
function, it indirectly causes Windows to invoke the WindowProc function, once for each message.
Then you can create a button through CreateWindow as the following code(But you need to set a unique identifier for subsequent operations):
#define IDB_BTN 1001
HWND btn = CreateWindow("BUTTON", "OPEN", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 500, 200, 100, 100, hwnd, (HMENU)IDB_BTN, (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
And you can open the Explorer in two ways.
You can open the explorer directly through ShellExecuteA
:
ShellExecute(NULL, "open", "explorer.exe", NULL, NULL, SW_NORMAL);
Of course maybe the best way to do this is with the SHOpenFolderAndSelectItems()
function.
LPCWSTR pszPathToOpen = L"C:\\Windows";
PIDLIST_ABSOLUTE pidl;
if (SUCCEEDED(SHParseDisplayName(pszPathToOpen, 0, &pidl, 0, 0)))
{
ITEMIDLIST idNull = { 0 };
LPCITEMIDLIST pidlNull[1] = { &idNull };
SHOpenFolderAndSelectItems(pidl, 1, pidlNull, 0);
ILFree(pidl);
}
Here is the complete sample:
#include <Windows.h>
#include <shlobj_core.h>
#define IDB_BTN 1001
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
// Register the window class.
TCHAR CLASS_NAME[] = "Sample Window Class";
MSG msg;
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
"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
);
HWND btn = CreateWindow(
"BUTTON",
"OPEN",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
500,
200,
100,
100,
hwnd,
(HMENU)IDB_BTN,
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
NULL);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDB_BTN:
{
//ShellExecute(NULL, "open", "explorer.exe", NULL, NULL, SW_NORMAL);
LPCWSTR pszPathToOpen = L"C:\\Windows";
PIDLIST_ABSOLUTE pidl;
if (SUCCEEDED(SHParseDisplayName(pszPathToOpen, 0, &pidl, 0, 0)))
{
ITEMIDLIST idNull = { 0 };
LPCITEMIDLIST pidlNull[1] = { &idNull };
SHOpenFolderAndSelectItems(pidl, 1, pidlNull, 0);
ILFree(pidl);
}
return 0;
}
default:
break;
};
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Upvotes: 2