C++ Win32, How to add a dropdown menu to a Win32 DialogBox - winapi

C++ Win32, How to add a dropdown menu to a Win32 DialogBox
Hi,
This is my first time posting quesiton to stackoverflow.
I am trying to add combobox (in menu.cpp) to a Win32 Dialogbox (in fingerspell.cpp). I am not very fluent in Win32
programming and most of the msdn example snippets draw a combobox inside a window. Even though Dialogbox is technically
a window but I haven't had much progress in modifing any window example code to handle a DialogBox. I would really appreciate a working example.
A rough sketch of the code is as follows. fingerspell.cpp creates implements the WinMain function and then calls up
other custom classes to draw inside this DialogBox. No other window controls, like buttons, text area etc, are used.
code for fingerspell.cpp is
#include "fingerspell.h"
extern "C" __declspec(dllexport)bool isGloveDriverInstalled();
extern "C" __declspec(dllimport)bool initialize();
#define RUN( x ) if ( SUCCEEDED( result ) ) { result = x; }
BOOL g_fullscreen = FALSE;
bool portReady;
INT_PTR CALLBACK OptionDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_INITDIALOG:
if (wParam == IDOK)
return TRUE ;
else
return FALSE ;
break;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED) {
if (LOWORD(wParam) == IDOK) {
g_fullscreen = TRUE;
EndDialog (hwndDlg, 1) ;
}
else if (LOWORD(wParam) == ID_WINDOW_OPT) {
g_fullscreen = FALSE;
EndDialog (hwndDlg, 1) ;
}
else {
EndDialog (hwndDlg, 0) ;
}
return TRUE ;
}
default:
return FALSE;
break ;
}
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
INT_PTR DispOption = DialogBox (hInstance, MAKEINTRESOURCE(IDD_DISPLAY_OPTIONS), NULL, OptionDialogProc) ;
if (DispOption == 0)
return 0 ;
//srand( GetTickCount( ) );
HRESULT result = S_OK;
if (!isGloveDriverInstalled())
{
portReady = FALSE;
MessageBox(NULL, "The Glove Driver is not istalled ", "Error", MB_OK );
}
else
{
if (!initialize())
{
portReady = FALSE;
MessageBox(NULL, "Error Opening Com Port", "Error", MB_OK );
}
else
{
portReady = TRUE;
}
}
RUN( Words ::Create ( "default.txt" ) );
RUN( Window::Create ( ) );
RUN( Render::Create ( ) );
RUN( Art ::Create ( ) );
RUN( Menu ::Create ( ) );
RUN( Window::MessageLoop( ) );
RUN( Menu ::Destroy ( ) );
RUN( Art ::Destroy ( ) );
RUN( Render::Destroy ( ) );
RUN( Window::Destroy ( ) );
RUN( Words ::Destroy ( ) );
if ( FAILED( result ) )
{
MessageBox( GetDesktopWindow( ), "Warning - Fail Code Detected", "Fingerspell 2002", MB_ICONWARNING | MB_OK );
}
return result;
}
code for menu.cpp. file where im trying to add combobox.
#include "fingerspell.h"
#include <windows.h> //include all the basics
#include <tchar.h> //string and other mapping macros
#include <string>
HRESULT Menu::Create( )
{
// set menu as the background
Render::SetBackground( ART_MENU );
// clear overlay
Render::Reset( );
Window::SetProc( Proc );
return S_OK;
}
HRESULT Menu::Destroy( void )
{
return S_OK;
}
LRESULT CALLBACK Menu::Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
DWORD i ;
const static RECT button_rect[ 8 ] =
{
{ 52, 139, 52 + 101, 139 + 50 }, //1. about
{ 55, 212, 55 + 85, 212 + 50 }, // 2. learn
{ 67, 280, 67 + 63, 280 + 50 }, // 3. exit
{ 397, 137, 397+ 233, 137 + 50 }, // 4. Add Delete List.
{ 421, 187, 421+ 183, 187 + 50 }, // 5. add word
{ 413, 247, 413+ 201, 247 + 50 }, // 6. delete word
{ 450, 300, 450+ 124, 300 + 50 }, // 7. practice
{ 473, 349, 473 + 82, 349 + 50 }, // 8. test
};
// custom message processing
switch ( uMsg )
{
case WM_CREATE:
return OnCreate(hwnd,reinterpret_cast<CREATESTRUCT*>(lParam));
case WM_MOUSEMOVE: // move is moved, see where is it pointing to.
{
int xPos = GET_X_LPARAM( lParam );
int yPos = GET_Y_LPARAM( lParam );
for ( i = 0; i < 8; i++ )
{
if ( xPos >= button_rect[ i ].left && yPos >= button_rect[ i ].top )
{
if ( xPos < button_rect[ i ].right && yPos < button_rect[ i ].bottom )
{
// set selection
Render::SetOverlay( 0, (ART) ( ART_MENU_LEARN + i ), button_rect[ i ].left, button_rect[ i ].top );
break;
}
}
}
if ( i == 8 )
{
//remove selection
Render::SetOverlay( 0, ART_NULL, 0, 0 );
}
return 0;
}
case WM_LBUTTONDOWN:
{
switch ( Render::GetOverlay( 0 ) )
{
case ART_MENU_EXIT: // done.
{
Menu::Destroy( );
Learn::Create( );
break;
}
case ART_MENU_LEARN: // done
{
Menu::Destroy( );
About::Create( );
break;
}
case ART_MENU_ABOUT: // done
{
Menu::Destroy( );
Test::Create( );
break;
}
case ART_MENU_TEST: // done.
{
Menu::Destroy( );
Practice::Create( );
break;
}
case ART_MENU_DELETEWORD: // done
{
Menu::Destroy( );
AddWord::Create( );
break;
}
case ART_MENU_ADDDELETELIST:
{
//Menu::Destroy () ;
PostQuitMessage( 0 );
break;
}
case ART_MENU_ADD:
{
Menu::Destroy( );
// About is place holder. should be AddDELETELIST
About::Create( );
break;
}
case ART_MENU_PRACTICE: // done.
{
Menu::Destroy( );
// About is place holder. shd be DELETEWORD.
About::Create( );
break;
}
}
return 0;
}
}
// default message processing
return DefWindowProc( hwnd, uMsg, wParam, lParam );
}
Thanks.

http://www.resedit.net/
I think it's better than visual studio editor (that comes only with professional)

On Vista or later, use a simple BS_SPLITBUTTON style of button control (WC_BUTTON), and then handle BCN_DROPDOWN to create your menu.
I haven't tried this actual code, but this sample looks reasonable: http://www.codereflect.com/2009/02/19/how-to-create-a-drop-down-button-in-windows-vista-7/
Martyn

Related

Handle SDL_KeyboardEvent without window focus

I'm trying to get keyboard events using SDL2.0. The following sample is working for me when I have the window's focus:
#include <SDL2/SDL.h>
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) != 0) /* Prefer only events SDL_INIT_EVENTS */
{
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
return 1;
}
SDL_Window* gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 320, SDL_WINDOW_SHOWN ); /* I don't want this window! */
/* While no quit */
bool quit = false;
//Event handler
SDL_Event e;
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
//User presses a key
else if( e.type == SDL_KEYDOWN )
{
printf( "Key type: %d\n", e.key.keysym.sym );
//Select surfaces based on key press
switch( e.key.keysym.sym )
{
case SDLK_UP:
printf( "UP!\n" );
break;
case SDLK_DOWN:
printf( "DOWN!\n" );
break;
case SDLK_LEFT:
printf( "LEFT!\n" );
break;
case SDLK_RIGHT:
printf( "RIGHT!\n" );
break;
default:
break;
}
}
}
}
SDL_Quit();
return 0;
}
I would like to avoid use SDL_Init(SDL_INIT_VIDEO) without create a SDL_Window using only SDL_Init(SDL_INIT_EVENTS). Actually, my problem is that I only can receive the events if I create the windows and focus it. Is it possible to get the events globally without the focus?
My strategy is to try to use SDL library to isolate OS events behavior and focus in record/play small events provided by an user. Other suggests are welcome.

Open an offline chart in MQL4 using [user32.dll] and [kernel32.dll] Win-API calls

I have the following code to open an offline chart in metatrader 4.
But all I could get it to do is open the offline file list. I am not
very familiar with windows programming so can someone tell me what am I doing wrong ?
#import "user32.dll"
int PostMessageA( int hWnd, int Msg, int wParam, int lParam );
int SendMessageA( int hWnd, int Msg, int wParam, int lParam );
int GetAncestor( int hWnd, int gaFlags );
int GetLastActivePopup( int hWnd );
int GetDlgItem( int hDlg, int nIDDlgItem );
#import
#import "kernel32.dll"
int FindFirstFileA( string Path, int& Answer[] );
bool FindNextFileA( int handle, int& Answer[] );
bool FindClose( int handle );
#import
#define WM_COMMAND 0x0111
#define WM_KEYDOWN 0x0100
#define VK_DOWN 0x28
#define BM_CLICK 0x00F5
#define GA_ROOT 2
#define PAUSE 100
string BuffToString( int& Buffer[] )
{
string Str = "";
int Pos = 11;
while ( Pos < 75 ) {
while ( Buffer[Pos] != 0 ) {
Str = Str + CharToStr( Buffer[Pos] & 0xFF );
Buffer[Pos] /= 0x100;
}
Pos++;
}
return( Str );
}
int GetChartPos( string FileName )
{
int Buffer[79];
int Pos = 0;
int handle = FindFirstFileA( TerminalPath() + "\history\\" + AccountServer() + "\\*.hst", Buffer );
if ( BuffToString( Buffer ) != FileName ) {
Pos++;
while ( FindNextFileA( handle, Buffer ) ) {
if ( BuffToString( Buffer ) == FileName )
break;
Pos++;
}
}
if ( handle > 0 )
FindClose( handle );
return( Pos );
}
int OpenOfflineList()
{
int hwnd = WindowHandle( Symbol(), Period() );
hwnd = GetAncestor( hwnd, GA_ROOT );
SendMessageA( hwnd, WM_COMMAND, 33053, 0 );
Sleep( PAUSE );
hwnd = GetLastActivePopup( hwnd );
return( hwnd );
}
void OpenOfflineChartbyNum( int ChartPos )
{
int hwnd1 = OpenOfflineList();
int hwnd2 = GetDlgItem( hwnd1, 1 );
hwnd1 = GetDlgItem( hwnd1, 0x487 );
while ( ChartPos >= 0 ) {
SendMessageA( hwnd1, WM_KEYDOWN, VK_DOWN, 0 );
ChartPos--;
}
Sleep( PAUSE );
SendMessageA( hwnd2, BM_CLICK, 0, 0 );
return;
}
void OpenOfflineChart( string Symb, int period )
{
OpenOfflineChartbyNum( GetChartPos( Symb + period + ".hst" ) );
return;
}
int init()
{
OpenOfflineChart( "AUDUSD", 120 );
return;
}
I'm not an expert in WinApi and the question is obviously old, but it is still relevant. So the problem is that you use FindFirstFileA(), which uses ANSI strings, but after 600 release MT4 uses Unicode, so you need to use FindFirstFileW() instead. Also, instead of SendMessage() you should use PostMessage() (pls don't ask me why). So here is the working code:
#import "user32.dll"
int PostMessageA( int hWnd, int Msg, int wParam, int lParam );
int SendMessageA( int hWnd, int Msg, int wParam, int lParam );
int GetAncestor( int hWnd, int gaFlags );
int GetLastActivePopup( int hWnd );
int GetDlgItem( int hDlg, int nIDDlgItem );
#import
#import "kernel32.dll"
int FindFirstFileW( string Path, ushort &Answer[] );
bool FindNextFileW( int handle, ushort &Answer[] );
bool FindClose( int handle );
#import
#define WM_COMMAND 0x0111
#define WM_KEYDOWN 0x0100
#define VK_DOWN 0x28
#define BM_CLICK 0x00F5
#define GA_ROOT 2
#define PAUSE 100
string BuffToString( int& Buffer[] )
{
string Str = "";
int Pos = 11;
while ( Pos < 75 ) {
while ( Buffer[Pos] != 0 ) {
Str = Str + CharToStr( Buffer[Pos] & 0xFF );
Buffer[Pos] /= 0x100;
}
Pos++;
}
return( Str );
}
int GetChartPos( string FileName )
{
ushort Buffer[300];
int Pos=-1;
string path = TerminalInfoString( TERMINAL_DATA_PATH ) + "\\history\\" + AccountInfoString( ACCOUNT_SERVER ) + "\\*.hst";
int handle = FindFirstFileW( path, Buffer );
string name = ShortArrayToString( Buffer, 22, 152 );
Pos++;
if(name!=FileName)
{
ArrayInitialize(Buffer,0);
while(FindNextFileW(handle,Buffer))
{
name=ShortArrayToString(Buffer,22,152);
Pos++;
if(name==FileName)
{
break;
}
ArrayInitialize(Buffer,0);
}
}
if(handle>0)
FindClose(handle);
return(Pos);
}
int OpenOfflineList()
{
int hwnd = WindowHandle( Symbol(), Period() );
hwnd = GetAncestor( hwnd, GA_ROOT );
PostMessageA( hwnd, WM_COMMAND, 33053, 0 );
Sleep( PAUSE );
hwnd = GetLastActivePopup( hwnd );
return( hwnd );
}
void OpenOfflineChartbyNum( int ChartPos )
{
int hwnd1 = OpenOfflineList();
int hwnd2 = GetDlgItem( hwnd1, 1 );
hwnd1 = GetDlgItem( hwnd1, 0x487 );
while ( ChartPos >= 0 ) {
PostMessageA( hwnd1, WM_KEYDOWN, VK_DOWN, 0 );
ChartPos--;
}
Sleep( PAUSE );
PostMessageA( hwnd2, BM_CLICK, 0, 0 );
return;
}
void OpenOfflineChart( string Symb, int period )
{
OpenOfflineChartbyNum( GetChartPos( Symb + period + ".hst" ) );
return;
}
int init()
{
OpenOfflineChart( "AUDUSD", 120 );
return;
}
But now ( Build 970+ ) it is much simpler to go with ChartOpen( "AUDUSD", 2 ); So, if you don't use custom names for symbols, you can replace all that with just one line of code.

Ruby implementation Win32API get mouse scroll/wheel input

I'm trying to use win32api on user32.dll to get mouse wheel input.
I tried the following:
#state = Win32API.new('user32','DefWindowProc',['i'],'i')
p #state.call(0x0800)
But it keeps returning 0 no matter what I do with my mouse wheel.
I thought something is wrong with my mouse, so I tried to do:
#state = Win32API.new('user32','GetKeyState',['L'],'L')
p #state.call(0x01) #left key
p #state.call(0x02) #right key
It worked, so I'm not sure what's wrong with the mouse wheel.
Regards
Edit 2/20/2014:
I tried to do the following:
GetActiveWindow = Win32API.new('user32','GetForegroundWindow','','i')
DefWindowProc = Win32API.new('user32','DefWindowProc','iiii','i')
DefWindowProc.call(GetActiveWindow.call,
Then, I got stuck with the UINT / Message (2nd argument).
Edit 2/20/2014:
I found the WM_MOUSEWHEEL message
Latest revision:
GetActiveWindow = Win32API.new('user32','GetForegroundWindow','','i')
DefWindowProc = Win32API.new('user32','DefWindowProc','iiii','i')
#WM_MOUSEWHEEL message 0x020A
DefWindowProc.call(GetActiveWindow.call, 0x020A,
Now I just need to figure out the 3rd and 4th argument.
As I don't know Ruby, I will give here a solution in C/C++ using only standard Win32 APIs. If you can call Win32 APIs from Ruby, that will work.
Note that the solution involves "callback" and "pointer". I know that's possible in Python (for example, with the ctypes module) and hope that same thing is possible with Ruby.
Register a Window Class and create a Window from that class, the window will be a Message-Only Window, so it will be invisible, with no GUI.
Use the RegisterRawInputDevices API to ask for raw events from mouse devices.
Set up a message loop, with the standard GetMessage/DispatchMessage combo.
Process the sent WM_INPUT message in your Window Procedure
4.1. Allocate memory for the raw datas
4.2. Retrieve the raw datas
4.3. Filter for mouse event and wheel datas
4.4. Process (I just print the wheel delta)
4.5. Free allocated memory.
Below, full source code. Build with VS2012 Express on Windows 7.
#include <Windows.h>
#include <stdio.h>
LRESULT CALLBACK MyWindowProc( HWND, UINT, WPARAM, LPARAM );
int main( void ) {
WNDCLASS WndClass;
memset( &WndClass, 0, sizeof( WndClass ) );
WndClass.hInstance = GetModuleHandle( NULL );
WndClass.lpszClassName = L"MyRawInputClass";
WndClass.lpfnWndProc = MyWindowProc;
RegisterClass( &WndClass );
HWND hWnd = CreateWindow( WndClass.lpszClassName, NULL, 0, 0, 0, 0, 0,
HWND_MESSAGE, 0, WndClass.hInstance, 0 );
RAWINPUTDEVICE RawInputDevice;
RawInputDevice.usUsagePage = 0x01; // Generic Desktop Controls
RawInputDevice.usUsage = 0x02; // Mouse
RawInputDevice.dwFlags = RIDEV_INPUTSINK;
RawInputDevice.hwndTarget = hWnd;
BOOL bWin32Success = RegisterRawInputDevices( &RawInputDevice, 1,
static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
BOOL bRet;
MSG msg;
while( ( bRet = GetMessage( &msg, hWnd, 0, 0 ) ) != 0 ) {
if (bRet != -1) {
DispatchMessage(&msg);
}
}
// NO GUI, UNREACHABLE
DestroyWindow( hWnd );
UnregisterClass( WndClass.lpszClassName, WndClass.hInstance );
return 0;
}
LRESULT CALLBACK MyWindowProc( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam ) {
switch ( uiMsg ) {
case WM_INPUT: {
UINT dwSize;
HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>( lParam );
UINT uiRetCode = GetRawInputData( hRawInput, RID_INPUT, NULL, &dwSize,
static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
if ( uiRetCode != 0xffffffff ) {
LPBYTE lpb = new BYTE[ dwSize ];
uiRetCode = GetRawInputData( hRawInput, RID_INPUT, lpb, &dwSize,
static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
if ( uiRetCode > 0 ) {
RAWINPUT* praw = reinterpret_cast<RAWINPUT*>( lpb );
if ( praw->header.dwType == RIM_TYPEMOUSE ) {
if ( praw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL ) {
signed int siDelta = static_cast<SHORT>( praw->data.mouse.usButtonData );
printf( "WHEEL EVENT: Delta = %d\n", siDelta );
}
}
}
delete[] lpb;
}
break;
} // WM_INPUT
default:
return DefWindowProc( hWnd, uiMsg, wParam, lParam );
}
return 0;
}

Win32 save text files from tabbed interface

I'm using MS visual c++ 2010 express to write a notepad program. I need to be able to save files from my tabbed interface ( each edit control is stored into a vector ). I can't seem to figure out how to save, depending on which edit control is visible to the user ( active tab ). Everything I've tried so far either doesn't save the contents or only saves from the first edit control. When the user adds a new file to the tabbed interface, it added that edit control to the back of the vector. This is my latest attempt:
std::vector<HWND>vect;
BOOL SaveTextFileFromEdit( HWND hEdit, LPCTSTR pszFileName )
{
HANDLE hFile;
BOOL bSuccess = FALSE;
hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
DWORD dwTextLength = GetWindowTextLength( hEdit );
if( dwTextLegth > 0 )
{
DWORD dwBufferSize = dwTextLength + 1;
LPSTR pszText = ( LPSTR )GlobalAlloc( GPTR, dwBufferSize );
if( pszText != NULL )
{
if( GetWindowText( hEdit, pszText, dwBufferSize ) )
{
DWORD dwWritten;
if( WriteFile( hFile, pszText, dwTextLength, &dwWritten, NULL ) )
bSuccess = TRUE;
}
GlobalFree( pszText );
}
}
CloseHandle( hFile );
}
return bSuccess;
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case ID_FILE_SAVEAS:
{
OPENFILENAME ofn;
char szFileName[ MAX_PATH ] = "";
ZeroMemory( &ofn, sizeof( ofn ) );
ofn.lStructSize = sizeof( ofn );
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = "txt";
ofn.flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
if( GetSaveFileName( &ofn ) )
{
HWND hEdit, hTabs;
hTabs = GetDlgItem( hwnd, IDC_MAIN_TAB );
int curTab = TabCtrl_GetCurSel( hTabs );
hEdit = GetDlgItem( hTabs, IDC_MAIN_EDIT );
// This is what i did have: hEdit = GetDlgItem( vect[ curTab ], IDC_MAIN_EDIT );
// Which wasn't saving anything
if( SaveTextFileFromEdit( hEdit, szFileName ) )
{
// EVERYTHING IS GOOD
}
}
}
break;
}
break;
}
return 0;
}
If the vector has each edit control's HWND then you don't need GetDlgItem at all: You already have the HWND that it would return.
hEdit = vect[ curTab ];

WM_COMMAND message not being received by the Windows Procedure

I am creating a system tray program with a shortcut/context menu, but I can't seem to receive WM_COMMAND messages in the Windows Procedure. It simply doesn't send when I click the menu item, and I've been checking for ages whether I have set up the menu correctly.
Here is my code:
#include <Windows.h>
#include <stdio.h>
#include "resource.h"
#define WM_TRAYICON (WM_USER + 0x0001) //a custom message for the notification icon
HWND hwnd; //window handle
HINSTANCE hinst; //module handle
WNDCLASSEX wnd; //window class
MSG msg; //event message or notification
NOTIFYICONDATA nid; //notification icon object
HMENU cmenu;
MENUITEMINFO menuitem1;
MENUITEMINFO menuitem2;
CURSORINFO cursor;
LRESULT CALLBACK MainWProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_COMMAND:
printf("asfd\r\n");
break;
case WM_CREATE:
printf("just created\r\n");
break;
case WM_TRAYICON:
switch( LOWORD(lParam) )
{
case WM_CONTEXTMENU:
GetCursorInfo( &cursor );
//printf("xPos: %d\r\nyPos = %d\r\n\r\n", xPos, yPos );
TrackPopupMenuEx( cmenu, TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_NOANIMATION | TPM_HORIZONTAL | TPM_VERTICAL, cursor.ptScreenPos.x, cursor.ptScreenPos.y, hwnd, NULL );
//DestroyMenu(
break;
}
break;
case WM_INITMENU:
printf("open menu\r\n");
break;
case WM_DESTROY:
//clean things up
Shell_NotifyIcon( NIM_DELETE, &nid );
break;
default:
break;
}
return DefWindowProc( hwnd, uMsg, wParam, lParam );
}
void main()
{
int result;
hinst = GetModuleHandle( NULL );
cursor.cbSize = sizeof( cursor );
memset( &wnd, 0, sizeof( wnd ) );
wnd.cbSize = sizeof( wnd );
wnd.lpszClassName = "MainWClass";
wnd.lpfnWndProc = MainWProc;
wnd.hInstance = hinst;
result = RegisterClassEx( &wnd );
hwnd = CreateWindowEx
(
0, //extended styles
wnd.lpszClassName, //class name
"Main Window", //window name
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL | WS_MINIMIZEBOX, //style tags
CW_USEDEFAULT, //horizontal position
CW_USEDEFAULT, //vertical position
CW_USEDEFAULT, //width
CW_USEDEFAULT, //height
(HWND) NULL, //parent window
(HMENU) NULL, //class menu
(HINSTANCE) wnd.hInstance, //some HINSTANCE pointer
NULL //Create Window Data?
);
if( !hwnd )
{
printf("CreateWindowEx failed: %d\n", GetLastError() );
Sleep( INFINITE );
}
nid.cbSize = sizeof( nid );
nid.hWnd = hwnd;
nid.uID = 1;
nid.uVersion = NOTIFYICON_VERSION_4;
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = LoadIcon( hinst, MAKEINTRESOURCE( IDI_ICON1 ) );
strcpy( nid.szTip, "My Tooltip!" );
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_SHOWTIP;
cmenu = CreatePopupMenu();
menuitem1.cbSize = sizeof( menuitem1 );
menuitem1.fMask = MIIM_TYPE;
menuitem1.fType = MFT_STRING;
menuitem1.hSubMenu = NULL;
//menuitem1.cch = ;
menuitem1.dwTypeData = "Open a world of wonder!";
InsertMenuItem( cmenu, 0, true, &menuitem1 );
if( ! Shell_NotifyIcon( NIM_ADD, &nid ) )
{
printf("Shell_NotifyIcon( NIM_ADD, &nid ) failed.\r\n");
Sleep( INFINITE );
}
if( ! Shell_NotifyIcon( NIM_SETVERSION, &nid ) )
{
printf("Shell_NotifyIcon( NIM_SETVERSION, &nid ) failed.\r\n");
Sleep( INFINITE );
}
UpdateWindow( hwnd );
for( ; ; )
{
if( GetMessage(&msg, hwnd, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
Um, you passed the TPM_RETURNCMD flag which means "don't post a WM_COMMAND message. Just return the value you would have posted."

Resources