I am trying to make a simple system tray icon app. Here is the heart of the code.
WNDCLASSEX wx = {};
wx.cbSize = sizeof( WNDCLASSEX );
wx.lpfnWndProc = WndProc; // function which will handle messages
wx.hInstance = hInstance;
wx.lpszClassName = szWindowClass;
if ( RegisterClassEx( &wx ) == 0 ) {
fileLogger->critical("Failed to register class");
return 0;
}
HWND hWnd = CreateWindowEx(
0, // _In_ DWORD dwExStyle,
szWindowClass, // _In_opt_ LPCTSTR lpClassName,
szTitle, // _In_opt_ LPCTSTR lpWindowName,
0, // _In_ DWORD dwStyle,
0, // _In_ int x,
0, // _In_ int y,
0, // _In_ int nWidth,
0, // _In_ int nHeight,
HWND_MESSAGE, // _In_opt_ HWND hWndParent,
NULL, // _In_opt_ HMENU hMenu,
hInstance, // _In_opt_ HINSTANCE hInstance,
NULL // _In_opt_ LPVOID lpParam
);
if ( hWnd == NULL )
{
fileLogger->critical("Failed to create window. Error code "+std::to_string(GetLastError()));
return 0;
}
NOTIFYICONDATA nid = {};
nid.uVersion = NOTIFYICON_VERSION_4;
nid.cbSize = sizeof( nid );
nid.hWnd = hWnd;
nid.guidItem = myGUID;
nid.uCallbackMessage = ICON_MESSAGE;
StringCchCopy( nid.szTip, sizeof( nid.szTip )/sizeof( nid.szTip[0] ), "Starting Client" );
// Loading a windows system icon for testing
LoadIconMetric( NULL, (PCWSTR)MAKEINTRESOURCE( IDI_ASTERISK ), LIM_LARGE, &(nid.hIcon) );
if ( ! Shell_NotifyIcon( NIM_ADD, &nid ) ) {
fileLogger->critical("Shell_NotifyIcon failure.");
return 0;
}
...
When I compile and run the executable from the command prompt, it creates a blank space in the system tray. I also returns immediately (maybe normal) even though the process is still running. I see no tooltip when I hover over the blank icon, and the blank spot persists until I manually terminate the program. The icon does not seem to be passing messages to WndProc when I click it.
Possible clue: According to every piece of documentation I've seen, this line
LoadIconMetric( NULL, (PCWSTR)MAKEINTRESOURCE( IDI_ASTERISK ), LIM_LARGE, &(nid.hIcon) );
Should be
LoadIconMetric( NULL, MAKEINTRESOURCE( IDI_ASTERISK ), LIM_LARGE, &(nid.hIcon) );
Why would I have to typecast it when apparently nobody else does?
That may or may not be related to my problem, but is definitely suspicious.
The first thing is that you don't set flags to indicate which fields are supplied:
nid.uFlags = NIF_ICON | NIF_TIP | NIF_GUID | NIF_MESSAGE;
I also suspect that you may have mixed Unicode / ASCII code. You should explicitly use wide char versions of functions.
Related
I cant create the window using code below although i get no error in compilation.Only a window with title of my project name appears.I also set hwnd=NULL after CreateWindowEx invocation to see whether MessageBox works but it does not work too.
#include <windows.h>
#include <StdAfx.h>
const char* myClassName="myWindowsClassName";
//The window procedure
LRESULT CALLBACK WndProc( HWND hwnd , UINT msg , WPARAM wParam , LPARAM lParam){
switch(msg){
case WM_CLOSE:
DestroyWindow( hwnd );
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc( hwnd , msg , wParam , lParam );
}
return 0;
}
//Registering window
int WINAPI WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lPCmdLine , int nCmdShow ){
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
wc.cbSize=sizeof( WNDCLASSEX );
wc.style=0;
wc.lpfnWndProc= WndProc;
wc.cbClsExtra=0;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon( NULL , IDI_APPLICATION);
wc.hCursor=LoadCursor(NULL , IDC_ARROW);
wc.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=NULL;
wc.lpszClassName= (LPCWSTR) myClassName;
wc.hIconSm=LoadIcon( NULL , IDI_APPLICATION );
if( !RegisterClassEx( &wc ) ){
MessageBox( NULL ,L"Window registeration failed" ,L"Error!" , MB_ICONEXCLAMATION | MB_OK );
return 0;
}
//Creating the window
hwnd=CreateWindowEx( WS_EX_CLIENTEDGE , (LPCWSTR)myClassName , L"The title of my window" , WS_OVERLAPPEDWINDOW , CW_USEDEFAULT , CW_USEDEFAULT, 320 , 240 , NULL , NULL , hInstance , NULL );
hwnd=NULL;
if( hwnd==NULL ){
MessageBox( NULL ,L"Window creation failed",L"Error!", MB_ICONEXCLAMATION | MB_OK );
return 0;
}
ShowWindow ( hwnd , nCmdShow );
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Where is the problem?
Thanks
Unicode vs ANSI mismatch?
myClassName is char* but you cast it to (LPCWSTR). If you are compiling as Unicode (and you should) then you should define the class name as const WCHAR* myClassName=L"myWindowsClassName"; and remove the casts (or use const_cast<LPTSTR>().
You also fail to initialize .cbWndExtra. Change WNDCLASSEX wc; to WNDCLASSEX wc = {};
You should perform better error checking to diagnose failures. Check on MSDN to see if a function sets the last error when it fails. If it does, call GetLastError() after the function fails.
I need to click on the "I Agree" button in the below code programmatically, could you please help? is this possible to use SendMessage(hButton, BM_CLICK, 0, 0); ?
typedef HRESULT STDAPICALLTYPE AcquireDeveloperLicense(
_In_opt_ HWND hwndParent,
_Out_ FILETIME *pExpiration
);
HINSTANCE hDll = LoadLibrary(TEXT("WSClient.dll"));
AcquireDeveloperLicense *acquire_license = (AcquireDeveloperLicense*)GetProcAddress(hDll, "AcquireDeveloperLicense");
FILETIME pExpiration = {};
HWND hwnd = GetConsoleWindow();
HRESULT result = acquire_license(hwnd, &pExpiration);
I am having a problem creating a simple window in C++ visual studio. I started a new "empty project" and only created one .cpp file. When I try to run the program, I get this error:
Unable to start program C:\...\Project1.exe. The system cannot find the file specified.
Why does this happen? I'm using visual studio 2010.
Here is my code:
#include <windows.h>
// Function prototypes.
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow );
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR szCmdLine,
int iCmdShow )
#pragma region part 1 - STARTUP STUFF
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = TEXT("Philip");
wc.lpszMenuName = 0; // no menu - ignore
wc.style = CS_HREDRAW | CS_VREDRAW; // Redraw the window
RegisterClass( &wc );
HWND hwnd = CreateWindow(
TEXT("Philip"),
TEXT("window's title!"),// appears in title of window
WS_OVERLAPPEDWINDOW,
10, 10,
200, 200,
NULL, NULL,
hInstance, NULL );
ShowWindow(hwnd, iCmdShow );
UpdateWindow(hwnd);
#pragma endregion
#pragma region part 2 - ENTER A LOOP TO CONTINUALLY KEEP CHECKING WITH WIN O/S FOR USER INTERACTION
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
#pragma endregion
return msg.wParam; // return from WinMain
}
LRESULT CALLBACK WndProc( HWND hwnd, // "handle" to the window that this message is for
UINT message, // TYPE of message (e.g. WM_PAINT is a message asking to paint the window)
WPARAM wparam, // information about the actual message
LPARAM lparam ) // MORE info about the message
{
switch( message )
{
case WM_CREATE:
// upon creation, let the speaker beep at 50Hz, for 10ms.
Beep( 50, 10 );
return 0;
break;
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint( hwnd, &ps );
// draw a circle and a 2 squares
Ellipse( hdc, 20, 20, 160, 160 );
Rectangle( hdc, 50, 50, 90, 90 );
Rectangle( hdc, 100, 50, 140, 90 );
EndPaint( hwnd, &ps );
}
return 0;
break;
case WM_DESTROY:
PostQuitMessage( 0 ) ;
return 0;
break;
}
return DefWindowProc( hwnd, message, wparam, lparam );
}
If you want to create a window then your kind of project is Windows Form Application (see picture above).
The solutions are an abstract concept to get together several projects. For example you could want to have a Windows Form Application using the features of a Class Library.
I want to implement a console inside my C++ application. Like ftp for example. Or (IIRC) sql, once you've connected to a Server.
Does anybody know a library which implements this? Ideally with auto-completion and such? My searches for this only come up with "how to build a C++ console application", which I do know how to do.
GNU Readline implements the features you want. If filename auto-completion is not the sort you need, use a custom auto-complete routine.
For Windows: Use AllocConsole() to attach a text console to your GUI app and freopen( "CON", "w", stdout ) ; to redirect and printf() to output text.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681944(v=vs.85).aspx
Sample code:
#include <stdio.h>
#include <stdlib.h>
// Function prototypes.
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow );
// In a C++ Windows app, the starting point is WinMain().
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow )
{
// these next few lines create and attach a console
// to this process. note that each process is only allowed one console.
AllocConsole() ;
freopen( "CON", "w", stdout ) ;
printf("HELLO!!! I AM THE CONSOLE!\n" ) ;
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof( WNDCLASSEX ) ;
wc.cbClsExtra = 0; // ignore for now
wc.cbWndExtra = 0; // ignore for now
wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = TEXT(" ");
wc.lpszMenuName = 0;
wc.style = CS_HREDRAW | CS_VREDRAW; // Redraw the window
RegisterClassEx( &wc );
HWND hwnd = CreateWindowEx( 0, TEXT(" "), TEXT("window's title!"), WS_OVERLAPPEDWINDOW, 10, 10, 200, 200, NULL, NULL, hInstance, NULL );
ShowWindow(hwnd, iCmdShow );
UpdateWindow(hwnd);
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return msg.wParam; // return from WinMain
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
switch( message )
{
case WM_CREATE:
// upon creation, let the speaker beep at 50Hz, for 10ms.
Beep( 50, 10 );
printf("HELLO!!! I AM THE CONSOLE!\n" ) ;
return 0;
break;
case WM_PAINT:
{
// we would place our Windows painting code here.
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint( hwnd, &ps );
// draw a circle and a 2 squares
Ellipse( hdc, 20, 20, 160, 160 );
Rectangle( hdc, 50, 50, 90, 90 );
Rectangle( hdc, 100, 50, 140, 90 );
printf("HELLO!!! I AM THE CONSOLE!\n" ) ;
EndPaint( hwnd, &ps );
}
return 0;
break;
case WM_LBUTTONDOWN:
printf("STOP POKING MEEE!!!\n") ;
break;
case WM_DESTROY:
PostQuitMessage( 0 ) ;
return 0;
break;
}
return DefWindowProc( hwnd, message, wparam, lparam );
}
If you want also autocomplete you could
check the example of linenoise (a lightweight readline alternative).
Basically you have to parse the Userinput Line in a Loop.
Example for a very basic CommadLineInterface :
show prompt and read input in a while loop,
call something like parseLine() on \n
split the Line in Tokens by at least Space (then ;) take the first String as Command cmd and the rest as args.
call dispatch(cmd, args);
In Visual Studio I generated a plain old Win32 application and stripped all the resources and generated code so that my application consists of this:
#include "stdafx.h"
#include "IcoTest.h"
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
::MessageBox( NULL, L"Testing", L"Test", MB_OK );
}
When I run the application, this is what I see:
So the question is can I change that default application icon in the taskbar? If so, what code needs to be added to do it?
Edit:
Here's what I did, and this kind of works but it isn't ideal. The new icon shows up alright, but the taskbar preview window in Vista doesn't work and the system menu doesn't work so I'm just going to leave it alone for now.
HWND CreateDummyWindow(HINSTANCE hInstance, int iconId, LPCTSTR taskbarTitle)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = DefWindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(iconId));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = 0;
wcex.lpszMenuName = 0;
wcex.lpszClassName = taskbarTitle,
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(iconId));
ATOM atom = RegisterClassEx(&wcex);
HWND wnd = ::CreateWindow(
wcex.lpszClassName, taskbarTitle, WS_ICONIC | WS_DISABLED,
-1000, -1000, 1, 1, NULL, NULL, hInstance, NULL);
return wnd;
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
HWND wnd = CreateDummyWindow(hInstance, IDI_ICON1, _T("Test") );
::MessageBox( wnd, _T("Testing"), _T("Test"), MB_OK );
::DestroyWindow( wnd );
}
The icon shown on the task bar is taken from the window itself. If the only window is the standard Windows MesssageBox, then you'll get some sort of OS default. You have to create your own window and give it an icon, then Windows will use that.
This looks like just sample code. If the real code is a non-console Windows application, you can do this:
Give your application's main window a task bar icon by calling SetIcon(). Then when you call MessageBox(), set the first parameter to the HWND of your application's main window.
For this particular case (one MessageBox call in the WinMain function) you could hook the message box dialog creation and set an icon there. Like this:
HHOOK g_hMsgBoxHook;
HINSTANCE g_hInstance;
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode == HC_ACTION)
{
CWPSTRUCT* pcwp = (CWPSTRUCT*)lParam;
if(pcwp->message == WM_INITDIALOG)
{
HICON hIcon = NULL;
HICON hIconBig = NULL;
// Small icon.
hIcon = (HICON)LoadImage(g_hInstance,
MAKEINTRESOURCE(IDI_MYICON),
IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
0);
if(hIcon)
{
SendMessage(pcwp->hwnd, WM_SETICON,
ICON_SMALL, (LPARAM)hIcon);
}
// Big icon.
hIconBig = (HICON)LoadImage(g_hInstance,
MAKEINTRESOURCE(IDI_MYICON),
IMAGE_ICON,
GetSystemMetrics(SM_CXICON),
GetSystemMetrics(SM_CXICON),
0);
if(hIconBig)
{
SendMessage(pcwp->hwnd, WM_SETICON,
ICON_BIG, (LPARAM)hIconBig);
}
}
}
return CallNextHookEx(g_hMsgBoxHook, nCode, wParam, lParam);
}
int CALLBACK wWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nCmdShow
)
{
g_hInstance = hInstance;
g_hMsgBoxHook = SetWindowsHookEx(WH_CALLWNDPROC,
CallWndProc, NULL, GetCurrentThreadId());
MessageBoxW(NULL, L"Testing", L"Test", MB_OK);
// ...
UnhookWindowsHookEx(g_hMsgBoxHook);
}
Where IDI_MYICON is the ID of your icon resource.
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
// ..
wndclass.hIconSm = ExtractIconEx( ... );
RegisterClassEx(&wndclass);
HWDN wnd = CreateWindow(...)
Why not just add an icon resource to the EXE? I'm pretty sure Windows will try that before falling back to the "generic" icons.
Create a form but never show it then assign it an icon and use that as the parent of your message box.
This hides the icon:
using (var f = new Form())
{
MessageBox.Show(f,"my message");
}
This will create an icon:
using (var f = new Form())
{
f.Icon = Resources.IconUpload;
f.Location=new Point(-1000,-1000);
f.StartPosition = FormStartPosition.Manual;
f.Show();
MessageBox.Show(f,"my message");
}