Skip navigation

Tag Archives: windows

I didn’t initialize the filename member:

GetOpenFileName fails if you do _not_ write a blank string to ofn.lpstrFile

Be sure to

 

sprintf( ofn.lpstrFile, “” ) ;

 

before calling OpenFileName

I didn’t know this, but an HINSTANCE is apparently a pointer to an IMAGE_DOS_HEADER struct.

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
  IMAGE_DOS_HEADER* header = (IMAGE_DOS_HEADER*)(hInstance) ;
  // ...
}

See this

A simple example that shows how to create a thread in C++ on Win32 platform

    #include <Windows.h>
    #include <stdio.h>
    
    struct Point
    {
      float x,y,z ;
    } ;
    
    DWORD WINAPI threadStartPoint( LPVOID data )
    {
      Sleep( 1000 ) ;
      Point *p = (Point*)data ;
      printf( "%f %f %f\n", p->x, p->y, p->z ) ;
      puts( "Thread job done" ) ;
      return 0 ;
    }
    
    // From main
    int main()
    {
      DWORD threadId ;
      Point p ;
      p.x=2, p.y=3, p.z=4 ;
      HANDLE handle = CreateThread( 0, 0, 
        threadStartPoint,
        (LPVOID)&p,
        0,
        &threadId
      ) ;
    
      if( !handle )
      {
        // Thread creation failed
        puts( "start fail\n" );
      }
      else
      {
        printf( "started on threadid=%d\n", threadId ) ;
      }
    
      WaitForSingleObject( handle, 2000 ) ; // wait up to 2000 ms for the other thread to complete before moving on
    
      puts( "main thread Exiting.." ) ;
      //system( "pause" ) ;
    }

Its annoying how they hide these, but they’re all available on the web.

SERVICE PACK 3

SERVICE PACK 2

The distance to initiate drag ‘n drop is controlled through this api..

Increasing their values helps to avoid accidental Copy of files into the same directory

#include <Windows.h>
#include <stdio.h>
int main()
{
  // DEFAULT VALUES ARE 4 and 4
  int cx,cy;
  cx = GetSystemMetrics( SM_CXDRAG ) ;
  cy = GetSystemMetrics( SM_CYDRAG ) ;
  
  printf( "cx=%d, cy=%d\n", cx, cy ) ;

  SystemParametersInfoA( SPI_SETDRAGHEIGHT, 90, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE ) ;
  SystemParametersInfoA( SPI_SETDRAGWIDTH, 90, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE ) ;


  cx = GetSystemMetrics( SM_CXDRAG ) ;
  cy = GetSystemMetrics( SM_CYDRAG ) ;
  
  printf( "cx=%d, cy=%d\n", cx, cy ) ;

 
}

Basic windows starter

// Win32

#include <windows.h>
#include <stdio.h>

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 )
{
  AllocConsole() ;
  AttachConsole( GetCurrentProcessId() ) ;
  freopen( "CON", "w", stdout ) ;
  puts( "************** Program start **************" ) ;
  WNDCLASSEX wcx = { 0 };
  wcx.cbSize = sizeof( WNDCLASSEX ) ;
  wcx.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
  wcx.hCursor = LoadCursor( NULL, IDC_ARROW );
  wcx.hIcon = LoadIcon( NULL, IDI_APPLICATION );
  wcx.hInstance = hInstance;
  wcx.lpfnWndProc = WndProc;
  wcx.lpszClassName = TEXT("BasicWindow");
  wcx.style = CS_HREDRAW | CS_VREDRAW;
  RegisterClassEx( &wcx );
  
  HWND hwnd = CreateWindowEx(
    0,
    TEXT("BasicWindow"),
    TEXT("Window 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 ;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
  switch( message )
  {
  case WM_CREATE:
    {
      // Stuff to do when the window is created
    }
    return 0;
    
  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 );

      EndPaint( hwnd, &ps );
    }
    return 0;

  case WM_KEYDOWN:
    {
      if( wparam == VK_ESCAPE )
      {
        PostQuitMessage( 0 ) ;
        return 0 ;
      }
    }
    break ;

  case WM_DESTROY:
    {
      PostQuitMessage( 0 ) ;
    }
    return 0;
  }

  return DefWindowProc( hwnd, message, wparam, lparam );
}

/////////////////////////////////////////////////////////////////
// AddingATimer.cpp                                            //
// Shows how to add a timer that causes Windows to pass us
// a WM_TIMER message every few seconds.
/////////////////////////////////////////////////////////////////
// USING THE WINDOWS TIMER:
// DEFINE some constants for the timers.
#define TIMER_SECOND 1		// first timer identified by integer 1
#define TIMER_MINUTE 2		// second timer identified by integer 2
// we will use these constants when we first create the timers,
// then Windows will use these numbers to notify us when each
// timer event has occurred.

#include <windows.h>



// Prototype for WndProc function
LRESULT CALLBACK WndProc ( HWND, UINT, WPARAM, LPARAM );

/////////////////////////////////////////////////////////////////
// WinMain:  Application entry point for Windows applications. //
//                                                             //
// Just as said every C++ program starts at main,              //
// every Windows program will start at WinMain.                //
/////////////////////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  LPSTR lpCmdLine, int nShowCmd )
{
  // String used to identify our application
  TCHAR applicationClassName[] = TEXT("FirstWindowApp");

#pragma region -_1.  CREATE THE WNDCLASSEX STRUCTURE/OBJECT_-
  WNDCLASSEX window;		// Look at members of this struct.
  // Below, we initialize all of them.

  window.cbClsExtra		= 0;						// extra bytes
  window.cbSize			= sizeof(WNDCLASSEX);		// keeps track of its own size
  window.cbWndExtra		= 0;						// extra bytes
  window.hbrBackground	= (HBRUSH) GetStockObject(WHITE_BRUSH);
  window.hCursor			= LoadCursor(NULL, IDC_HAND);	// load hand cursor
  //Tip:  type in IDC_ then press CTRL+SPACE to get a list of avail. cursors

  window.hIcon			= LoadIcon(NULL, IDI_APPLICATION);	// large icon
  window.hIconSm			= LoadIcon(NULL, IDI_APPLICATION);	// small icon that shows up in top left of window
  window.hInstance		= hInstance;				// program's instance handle that was first passed to WinMain by windows when program was first run
  window.lpfnWndProc		= WndProc;					// function pointer to WndProc function
  window.lpszClassName	= applicationClassName;		// window class name.. defined above
  window.lpszMenuName		= NULL;						// main menu
  window.style			= CS_OWNDC | CS_HREDRAW | CS_VREDRAW;	// redraw on horizontal or vertical resize
#pragma endregion

#pragma region -_2.  REGISTER THAT WNDCLASSEX STRUCTURE WITH WINDOWS O/S + CREATE WINDOW_-
  if(!RegisterClassEx( &window ))
  {
    MessageBox(NULL, TEXT("Something's wrong.. quitting"), TEXT("error"), MB_OK);
    return 1;		// return from WinMain.. i.e. quit
  }

  // CREATE THE WINDOW AND KEEP THE HANDLE TO IT.
  HWND		hwnd;			// declare a handle to a window
  hwnd = CreateWindowExW(	WS_EX_TOPMOST,			// extended window style.. this sets the window to being always on top
    applicationClassName,	// window class name.. defined above
    TEXT("WINDOW TITLE"),	// title bar of window
    WS_OVERLAPPEDWINDOW,	// window style
    CW_USEDEFAULT, 40,		// initial x, y start position of window
    // CW_USEDEFAULT means "let Windows choose it"

    400, 160,				// initial width, height of window
    NULL, NULL,				// parent window, window menu
    hInstance, NULL);		// program instance handle, creation params

  // now we show and paint our window, so it appears
  ShowWindow(hwnd, nShowCmd );		// you have to ask that your Window be shown to see it
  UpdateWindow(hwnd);					// paint the window

#pragma endregion

#pragma region -_3.  MESSAGE LOOP_-

  MSG			msg;
  // this is the struct that holds the message
  // msg.hwnd - handle to the window to whom the message is for
  // msg.message - type of message for the window (mouse click, key press, key up, etc)
  // msg.lParam - a parameter that contains data.  the data it contains DEPENDS ON THE MESSAGE!!
  // msg.wParam - a parameter that contains data.  the data it contains DEPENDS ON THE MESSAGE!!
  // msg.time - the time the message was created
  // msg.pt - cursor position in screen coordinates when message was posted

  // enter the message loop
  while(GetMessage(&msg, NULL, 0, 0))
  {
    TranslateMessage(&msg);	
    DispatchMessage(&msg);	// send off to WndProc for processing
  }
#pragma endregion

  return 0;	// end program once we exit the message loop
}

////////////////////////////////////////////////////////////////////////
// WndProc - "Window procedure" function -- this function gets called
// by Windows whenever there is a "message" available for
// your window.
// A "message" is available for your window whenever something "happens"
// to it -- i.e. the user clicks on it, or the user types a key when your
// window has "input focus"
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  HDC			hdc;
  PAINTSTRUCT	ps;
  RECT		rect;

  // this switch looks at the message that was passed to the WndProc function.
  // There are tons of possible messages..
  // WM_CREATE:	// message passed to WndProc when the window is first created
  // WM_PAINT:	// message passed when there is a request from O/S to paint window
  // WM_KEYDOWN:	// message passed when a key is being pressed down.. see MSDN for more

  // Generally, all messages to the window will start with WM_
  switch(message)
  {
  case WM_CREATE:			// WndProc gets sent the WM_CREATE message when
    {					// the window is first created

      // (if you don't have the 8254 chip (lots of modern pc's don't!))
      MessageBeep( 1 ) ;

      // upon creation, beep 3 times @ 500Hz
      //Beep( 500, 10 );
      //Beep( 500, 10 );
      //Beep( 500, 10 );


      // Upon window creation, we want to initialize the timers:
      SetTimer( hwnd, TIMER_SECOND, 1000, NULL );
      SetTimer( hwnd, TIMER_MINUTE, 60000, NULL );
      return 0;		// return from WndProc
    }
    break;

  case WM_PAINT:
    {
      // if the message was "paint the window", just draw the text "This is my window..."
      hdc = BeginPaint(hwnd, &ps);		// hdc is a "handle to a device context"
      GetClientRect(hwnd, &rect);			// the "client rectangle" is the window area but
      // EXCLUDING the title bar and borders
      DrawText(hdc, TEXT("This is my window..."), -1, &rect, DT_SINGLELINE | DT_BOTTOM | DT_VCENTER );
      EndPaint(hwnd, &ps);
      return 0;
    }
    break;

  case WM_DESTROY:
    {
      PostQuitMessage(0);
      return 0;
    }
    break;

    // +++ new.
  case WM_TIMER:
    {
      switch(wParam)
      {
      case TIMER_SECOND:
        //Beep(200, 20);		// just tick every time the WM_TIMER message is passed
        MessageBeep( 1 ) ;
        break;
      case TIMER_MINUTE:
        //Beep(700, 100);		// beep higher every minute
        MessageBeep( 1 ) ;
      }
      return 0;
    }
    break;

  }

  // If message was NOT handled by us, we pass it off to
  // the windows operating system to handle it.
  return DefWindowProc(hwnd, message, wParam, lParam);
}




On Windows machines, almost every system I’ve seen starts with a C:\ drive.

You know, I still remember the days when the C:\ drive was new, and it was neat, because it meant you had a hard disk, which made this cool deep drilling sound when you accessed it.

A:\ and B:\ were the floppy disk drives. Usually you had something in the A:\ drive. When I was a kid, when we had the IBM PC Junior, if you wanted to play a game, you popped it into the A:\ drive and booted up. Digger was my favorite, then Styx.

I haven’t seen a machine with a floppy disk drive since… I don’t know when. Certainly not a NEW PC in well over 3-5 years now.

So machines today though, still start at C:\. Why? Well, the USB drive is removable.. its not a fixed thing, so it’d make little sense to make the “usb drive” A:\.

So what can you make A:\?

* CD/DVD-ram drive?
* primary hard disk partition!

I’d like to see, in the future, a 1G FAST “RAMDRIVE”. that’d be cool. when machines get ridiculous amounts of RAM (like 64G or something), you can allocate 2G of that RAM to an A:\ drive which gets wiped on computer shutdown. Its a GREAT scratch disk though – for putting stuff that you will only have there temporarily. Also it’d make a great recycling bin, requiring you to decided whether to delete or keep something on windows shutdown.

I personally just bought a new hard disk. And instead of making it E:\ or F:\, I decided to make it B:\. Hey! That’s new and unusual. I just couldn’t bring myself to make it A:\.

windows 3.1 i wanted windows 95.
windows 95. i wanted windows 98, kinda.

windows 95. i REALLY wanted winxp.

winxp. wanted vista.

vista. back to xp.

xp. want windows 7? eah, not sure.

xp is good.

windows 7 RC? use it for a year? eah. I want xp.

do you see how one mess up, one “bad release” (yes, I HAVE tried it) – you just can’t have an o/s start up, look all fine, then it jump down your throat for “needing permission” to move a basic file.

i created my login name as “root”! what more do you want?

sheesh. i mean, if they want to shove security issues down my throat, they really shouldn’t do it this way.

also being a developer, I don’t like the “toy” messages – “this application has stopped working”

What? then start it back up again! vista, why are you screwing with me?

I mean, saying “the application BROKE” would make more sense. But “has stopped working” is just too gay and “politically correct” – it still makes me think that vista is behind the application “stopping to work”.

I do not like the vista LOOK. the aero scheme, and the new window layouts, i think its because i’m sour on vista. what was so sleek and cool when it first come out turned out to be a lie and a signature for “SLOW” – the one thing I cannot stand from my machine.

I’m HAPPY to hear that Windows 7 is a huge improvement over vista – that its like the “new XP” that everyone wanted for christmas in 2006. I’m not trying the beta or the RC, I don’t think. I’m just going to wait and hope it doesn’t suck.

Windows and windowing

  • Taskix for changing the order of windows in the taskbar
  • Ultramon for having a taskbar appear on each monitor

General tools

  • Winspector for examining Windows messages
  • Winmerge for code file diffing
  • WinDiff for diffing either single files, or entire folders. This is a powerful program, don’t let its simple appearance deceive you. Comes with Windows SDK, if you develop for Windows you probably already have it.
  • Regex Coach for testing out regular expressions
  • TCPView for looking at net connections that are active, and what program is using it
  • the rest of the SysInternals suite (great tools!)
  • PuTTY for telnet
  • a href=”http://www.oldversion.com/download_WS_FTP_LE_6.html”>ws_ftp 6 for FTP file transfers, before it became bloatware
  • DaemonTools – mounts DVD images to your hard disk, though i like poweriso as well (*poweriso is not free, its shareware)
  • Teracopy. For copying files between disks. This application is BLAZINGLY fast, you won’t believe it – if you’re used to Windows Explorer copies.

media/mp3

  • GoldWave – a fantastic recorder/wav/sound editor
  • Winamp – just THE BEST media player. Now plays FLV!
  • VLC for all those avi’s that just refuse to play with anything else

NES and games

Web

(this section lacking, i know)

  • Not so much these days, but multiple ie gives you ie 6

Windows directory comparison tool

I was LOOKING for one for a long time. I finally found one, right on my own system!!

C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin\x64\WinDiff.Exe

There’s also: SyncToy

So it comes with the Windows SDK. Try searching for WinDiff on your computer

If you don’t already have it, then you can get it here.

I use it mostly because I keep redundant copies of entire folders, a lot of the time. For example, when my laptop was going down (lost ability to recharge from wall.. it was gonna go in for repairs!) i made an emergency dump of all the files that were on it. Some of the code files I had several copies of already, so WinDiff expedites the process of being able to blow away entire folders that are completely redundant -

Its pretty neat.

You can also blow out the thing, to see the actual file that is causing the diff

Well, to quote the great master:

When Windows needs to load a DLL module before running a program that requires it, the library file must be stored in the directory containing the .EXE program, the current directory, the Windows system directory, the Windows directory, or a directory accessible through the PATH string in
the MS-DOS environment. (The directories are searched in that order.)

Programming Windows 5th edition, page 962

MSDN ref

debugview. open it and it intercepts debug messages from system and shows them to you. very useful when debugging direct3d apps.

winspector

screen-full

! OK. Finally

Download the esnips code package to get green_man.ico!


/////////////////////////////////////////////
//                                         //
// Minimizing C++ Win32 App To System Tray //
//                                         //
// You found this at bobobobo's weblog,    //
// http://bobobobo.wordpress.com           //
//                                         //
// Creation date:  Mar 30/09               //
// Last modified:  Mar 30/09               //
//                                         //
/////////////////////////////////////////////

// GIVING CREDIT WHERE CREDIT IS DUE!!
// Thanks ubergeek!  http://www.gidforums.com/t-5815.html

#pragma region include and define
#include <windows.h>
#include <shellapi.h>
#include <stdio.h>

#ifdef UNICODE
#define stringcopy wcscpy
#else
#define stringcopy strcpy
#endif

#define ID_TRAY_APP_ICON                5000
#define ID_TRAY_EXIT_CONTEXT_MENU_ITEM  3000
#define WM_TRAYICON ( WM_USER + 1 )
#pragma endregion

#pragma region constants and globals
UINT WM_TASKBARCREATED = 0 ;

HWND g_hwnd ;
HMENU g_menu ;

NOTIFYICONDATA g_notifyIconData ;
#pragma endregion


LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);



#pragma region helper funcs
// These next 2 functions are the STARS of this example.
// They perform the "minimization" function and "restore"
// functions for our window.  Notice how when you "minimize"
// the app, it doesn't really "minimize" at all.  Instead,
// you simply HIDE the window, so it doesn't display, and
// at the same time, stick in a little icon in the system tray,
// so the user can still access the application.
void Minimize()
{
  // add the icon to the system tray
  Shell_NotifyIcon(NIM_ADD, &g_notifyIconData);

  // ..and hide the main window
  ShowWindow(g_hwnd, SW_HIDE);
}

// Basically bring back the window (SHOW IT again)
// and remove the little icon in the system tray.
void Restore()
{
  // Remove the icon from the system tray
  Shell_NotifyIcon(NIM_DELETE, &g_notifyIconData);

  // ..and show the window
  ShowWindow(g_hwnd, SW_SHOW);
}

// Initialize the NOTIFYICONDATA structure.
// See MSDN docs http://msdn.microsoft.com/en-us/library/bb773352(VS.85).aspx
// for details on the NOTIFYICONDATA structure.
void InitNotifyIconData()
{
  memset( &g_notifyIconData, 0, sizeof( NOTIFYICONDATA ) ) ;
  
  g_notifyIconData.cbSize = sizeof(NOTIFYICONDATA);
  
  /////
  // Tie the NOTIFYICONDATA struct to our
  // global HWND (that will have been initialized
  // before calling this function)
  g_notifyIconData.hWnd = g_hwnd;
  // Now GIVE the NOTIFYICON.. the thing that
  // will sit in the system tray, an ID.
  g_notifyIconData.uID = ID_TRAY_APP_ICON;
  // The COMBINATION of HWND and uID form
  // a UNIQUE identifier for EACH ITEM in the
  // system tray.  Windows knows which application
  // each icon in the system tray belongs to
  // by the HWND parameter.
  /////
  
  /////
  // Set up flags.
  g_notifyIconData.uFlags = NIF_ICON | // promise that the hIcon member WILL BE A VALID ICON!!
    NIF_MESSAGE | // when someone clicks on the system tray icon,
    // we want a WM_ type message to be sent to our WNDPROC
    NIF_TIP;      // we're gonna provide a tooltip as well, son.

  g_notifyIconData.uCallbackMessage = WM_TRAYICON; //this message must be handled in hwnd's window procedure. more info below.
  
  // Load da icon.  Be sure to include an icon "green_man.ico" .. get one
  // from the internet if you don't have an icon
  g_notifyIconData.hIcon = (HICON)LoadImage( NULL, TEXT("green_man.ico"), IMAGE_ICON, 0, 0, LR_LOADFROMFILE  ) ;

  // set the tooltip text.  must be LESS THAN 64 chars
  stringcopy(g_notifyIconData.szTip, TEXT("Green man.. here's looking at ya!"));
}
#pragma endregion

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR args, int iCmdShow )
{
  TCHAR className[] = TEXT( "tray icon class" );

  // I want to be notified when windows explorer
  // crashes and re-launches the taskbar.  the WM_TASKBARCREATED
  // event will be sent to my WndProc() AUTOMATICALLY whenever
  // explorer.exe starts up and fires up the taskbar again.
  // So its great, because now, even if explorer crashes,
  // I have a way to re-add my system tray icon in case
  // the app is already in the "minimized" (hidden) state.
  // if we did not do this an explorer crashed, the application
  // would remain inaccessible!!
  WM_TASKBARCREATED = RegisterWindowMessageA("TaskbarCreated") ;

  #pragma region add a console
  // add a console, because I love consoles.
  // To disconnect the console, just comment out
  // the next 3 lines of code.
  //// AllocConsole();
  //// AttachConsole( GetCurrentProcessId() ) ;
  //// freopen( "CON", "w", stdout ) ;
  #pragma endregion
  
  #pragma region get window up
  WNDCLASSEX wnd = { 0 };

  wnd.hInstance = hInstance;
  wnd.lpszClassName = className;
  wnd.lpfnWndProc = WndProc;
  wnd.style = CS_HREDRAW | CS_VREDRAW ;
  wnd.cbSize = sizeof (WNDCLASSEX);

  wnd.hIcon = LoadIcon (NULL, IDI_APPLICATION);
  wnd.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
  wnd.hCursor = LoadCursor (NULL, IDC_ARROW);
  wnd.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE ;
  
  if (!RegisterClassEx(&wnd))
  {
    FatalAppExit( 0, TEXT("Couldn't register window class!") );
  }
  
  g_hwnd = CreateWindowEx (
    
    0, className,
    
    TEXT( "Using the system tray" ),
    WS_OVERLAPPEDWINDOW,
    
    CW_USEDEFAULT, CW_USEDEFAULT, 
    400, 400, 

    NULL, NULL, 
    hInstance, NULL
  );

  // Add the label with instruction text
  CreateWindow( TEXT("static"), TEXT("right click the system tray icon to close"), WS_CHILD | WS_VISIBLE | SS_CENTER,
                  0, 0, 400, 400, g_hwnd, 0, hInstance, NULL ) ;
  
  // Initialize the NOTIFYICONDATA structure once
  InitNotifyIconData();


  ShowWindow (g_hwnd, iCmdShow);
  #pragma endregion

  MSG msg ;
  while (GetMessage (&msg, NULL, 0, 0))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }


  // Once you get the quit message, before exiting the app,
  // clean up and remove the tray icon
  if( !IsWindowVisible( g_hwnd ) )
  {
    Shell_NotifyIcon(NIM_DELETE, &g_notifyIconData);
  }

  return msg.wParam;
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  if ( message==WM_TASKBARCREATED && !IsWindowVisible( g_hwnd ) )
  {
    Minimize();
    return 0;
  }

  switch (message)
  {
  case WM_CREATE:

    // create the menu once.
    // oddly, you don't seem to have to explicitly attach
    // the menu to the HWND at all.  This seems so ODD.
    g_menu = CreatePopupMenu();

    AppendMenu(g_menu, MF_STRING, ID_TRAY_EXIT_CONTEXT_MENU_ITEM,  TEXT( "Exit" ) );

    break;
  
  case WM_SYSCOMMAND:
    switch( wParam & 0xfff0 )  // (filter out reserved lower 4 bits:  see msdn remarks http://msdn.microsoft.com/en-us/library/ms646360(VS.85).aspx)
    {
    case SC_MINIMIZE:
    case SC_CLOSE:  // redundant to WM_CLOSE, it appears
      Minimize() ; 
      return 0 ;
      break;
    }
    break;


  // Our user defined WM_TRAYICON message.
  // We made this message up, and we told
  // 
  case WM_TRAYICON:
    {
      printf( "Tray icon notification, from %d\n", wParam ) ;
      
      switch(wParam)
      {
      case ID_TRAY_APP_ICON:
        printf( "Its the ID_TRAY_APP_ICON.. one app can have several tray icons, ya know..\n" ) ;
        break;
      }

      // the mouse button has been released.
      
      // I'd LIKE TO do this on WM_LBUTTONDOWN, it makes
      // for a more responsive-feeling app but actually
      // the guy who made the original post is right.
      // Most apps DO respond to WM_LBUTTONUP, so if you
      // restore your window on WM_LBUTTONDOWN, then some
      // other icon will scroll in under your mouse so when
      // the user releases the mouse, THAT OTHER ICON will
      // get the WM_LBUTTONUP command and that's quite annoying.
      if (lParam == WM_LBUTTONUP)
      {
        printf( "You have restored me!\n" ) ;
        Restore();
      }
      else if (lParam == WM_RBUTTONDOWN) // I'm using WM_RBUTTONDOWN here because
      {
        printf( "Mmm.  Let's get contextual.  I'm showing you my context menu.\n" ) ;
        // it gives the app a more responsive feel.  Some apps
        // DO use this trick as well.  Right clicks won't make
        // the icon disappear, so you don't get any annoying behavior
        // with this (try it out!)

        // Get current mouse position.
        POINT curPoint ;
        GetCursorPos( &curPoint ) ;
        
        // should SetForegroundWindow according
        // to original poster so the popup shows on top
        SetForegroundWindow(hwnd); 

        
        
        // TrackPopupMenu blocks the app until TrackPopupMenu returns
        printf("calling track\n");
        UINT clicked = TrackPopupMenu(
          
          g_menu,
          TPM_RETURNCMD | TPM_NONOTIFY, // don't send me WM_COMMAND messages about this window, instead return the identifier of the clicked menu item
          curPoint.x,
          curPoint.y,
          0,
          hwnd,
          NULL

        );
        printf("returned from call to track\n");


        // Original poster's line of code.  Haven't deleted it,
        // but haven't seen a need for it.
        //SendMessage(hwnd, WM_NULL, 0, 0); // send benign message to window to make sure the menu goes away.
        if (clicked == ID_TRAY_EXIT_CONTEXT_MENU_ITEM)
        {
          // quit the application.
          printf("I have posted the quit message, biatch\n");
          PostQuitMessage( 0 ) ;
        }
      }
    }
    break;

  // intercept the hittest message.. making full body of
  // window draggable.
  case WM_NCHITTEST:
  {
    // http://www.catch22.net/tuts/tips
    // this tests if you're on the non client area hit test
    UINT uHitTest = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam);
    if(uHitTest == HTCLIENT)
      return HTCAPTION;
    else
      return uHitTest;
  }

  case WM_CLOSE:
    printf( "Got an actual WM_CLOSE Message!  Woo hoo!\n" ) ;
    Minimize() ;
    return 0;
    break;

  case WM_DESTROY:
    printf( "DESTROY!!\n" ) ;
    PostQuitMessage (0);
    break;

  }

  return DefWindowProc( hwnd, message, wParam, lParam ) ;
}



Download esnips code package (thanks esnips! :)

Follow

Get every new post delivered to your Inbox.

Join 42 other followers