Skip navigation

Monthly Archives: November 2010

I keep losing this, it came originally from Game Audio Programming by James Boer:

    Frequencies for equal tempered tuning
    1    2    3     4     5    6     7     8     ( octave )
C   32   65   131   262   523  1047  2093  4186
C#  35   69   139   277   554  1109  2218  4435
D   37   73   147   294   587  1175  2349  4699
D#  39   78   156   311   622  1245  2489  4978
E   41   82   165   330   659  1319  2637  5274
F   44   87   175   349   698  1397  2794  5588
F#  46   93   185   370   740  1480  2960  5920
G   49   98   196   392   784  1568  3136  6272
G#  52   104  208   415   831  1661  3322  6645
A   55   110  220   440   880  1760  3520  7040
A#  58   117  233   466   932  1865  3729  7459
B   61   123  247   494   988  1976  3951  7902

/////////////////////////////////////////////////////////////////
// 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);
}




#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;

#pragma comment( lib, "gdiplus.lib" )
#pragma warning( disable : 4018 )
#pragma warning( disable : 4996 )

LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );

INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow )
{
  // attach a console
  AllocConsole();
  AttachConsole( GetCurrentProcessId() );
  freopen( "CON", "w", stdout );

  // Start up GDI+.
  GdiplusStartupInput gdiplusStartupInput;
  ULONG_PTR gdiplusToken;
  GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL );

  WNDCLASSEX wndClassex = { 0 };
  wndClassex.cbClsExtra     = 0;
  wndClassex.cbSize         = sizeof( WNDCLASSEX ) ;
  wndClassex.cbWndExtra     = 0;
  
  wndClassex.hbrBackground  = ( HBRUSH )GetStockObject( WHITE_BRUSH );
  wndClassex.hCursor        = LoadCursor( NULL, IDC_ARROW );
  wndClassex.hIcon          = LoadIcon( NULL, IDI_APPLICATION );
  wndClassex.hIconSm        = NULL;
  wndClassex.hInstance      = hInstance;
  wndClassex.lpfnWndProc    = WndProc;
  wndClassex.lpszClassName  = TEXT( "GDIPLUSWINDOW" );
  wndClassex.lpszMenuName   = NULL;
  wndClassex.style          = CS_HREDRAW | CS_VREDRAW;

  if( !RegisterClassEx( &wndClassex ) ) { puts( "problem registering wndclassex" ); system("pause"); return 1; }
  HWND hWnd = CreateWindowEx( 0,
    TEXT( "GDIPLUSWINDOW" ),   // window class name
    TEXT( "Welcome to GDI+!" ),  // window caption
    WS_OVERLAPPEDWINDOW,      // window style
    20,            // initial x position
    20,            // initial y position
    640,            // initial width
    480,            // initial height
    NULL,                     // parent window handle
    NULL,                     // window menu handle
    hInstance,                // program instance handle
    NULL );                    // creation parameters

  ShowWindow( hWnd, iCmdShow );
  UpdateWindow( hWnd );

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

  GdiplusShutdown( gdiplusToken );
  return msg.wParam;
}

void MessageBox( TCHAR* fmt, TCHAR* title, int options, va_list args )
{
  TCHAR buf[ 1024 ];
  int index = wvsprintf( buf, fmt, args );
  buf[index] = '\n';
  buf[index+1] = 0;
  wprintf( buf );
  MessageBox( HWND_DESKTOP, buf, title, options );
}

void info( TCHAR* fmt, ... )
{
  va_list list;
  va_start( list, fmt );
  MessageBox( fmt, TEXT( "Info" ), MB_OK|MB_ICONINFORMATION, list );
}

void error( TCHAR* fmt, ... )
{
  va_list list;
  va_start( list, fmt );
  MessageBox( fmt, TEXT( "Error" ), MB_OK|MB_ICONERROR, list );
}

TCHAR* GetStatusString( Gdiplus::Status status )
{
  TCHAR* statuses[] = {
    TEXT( "Ok: Indicates that the method call was successful." ),
    TEXT( "GenericError: Indicates that there was an error on the method call, which is identified as something other than those defined by the other elements of this enumeration." ),
    TEXT( "InvalidParameter: Indicates that one of the arguments passed to the method was not valid." ),
    TEXT( "OutOfMemory: Indicates that the operating system is out of memory and could not allocate memory to process the method call. For an explanation of how constructors use the OutOfMemory status, see the Remarks section at the end of this topic." ),
    TEXT( "ObjectBusy: Indicates that one of the arguments specified in the API call is already in use in another thread." ),
    TEXT( "InsufficientBuffer: Indicates that a buffer specified as an argument in the API call is not large enough to hold the data to be received." ),
    TEXT( "NotImplemented: Indicates that the method is not implemented." ),
    TEXT( "Win32Error: Indicates that the method generated a Win32 error." ),
    TEXT( "WrongState: Indicates that the object is in an invalid state to satisfy the API call. For example, calling Pen::GetColor from a pen that is not a single, solid color results in a WrongState status." ),
    TEXT( "Aborted: Indicates that the method was aborted." ),
    TEXT( "FileNotFound: Indicates that the specified image file or metafile cannot be found." ),
    TEXT( "ValueOverflow: Indicates that the method performed an arithmetic operation that produced a numeric overflow." ),
    TEXT( "AccessDenied: Indicates that a write operation is not allowed on the specified file." ),
    TEXT( "UnknownImageFormat: Indicates that the specified image file format is not known." ),
    TEXT( "FontFamilyNotFound: Indicates that the specified font family cannot be found. Either the font family name is incorrect or the font family is not installed." ),
    TEXT( "FontStyleNotFound: Indicates that the specified style is not available for the specified font family." ),
    TEXT( "NotTrueTypeFont: Indicates that the font retrieved from an HDC or LOGFONT is not a TrueType font and cannot be used with GDI+." ),
    TEXT( "UnsupportedGdiplusVersion: Indicates that the version of GDI+ that is installed on the system is incompatible with the version with which the application was compiled." ),
    TEXT( "GdiplusNotInitialized: Indicates that the GDI+API is not in an initialized state. To function, all GDI+ objects require that GDI+ be in an initialized state. Initialize GDI+ by calling GdiplusStartup." ),
    TEXT( "PropertyNotFound: Indicates that the specified property does not exist in the image." ),
    TEXT( "PropertyNotSupported: Indicates that the specified property is not supported by the format of the image and, therefore, cannot be set." ),
    TEXT( "ProfileNotFound: Indicates that the color profile required to save an image in CMYK format was not found." ),
    TEXT( "INVALID STATUS CODE" )
  };
  if( status < 0 || status > Gdiplus::Status::PropertyNotSupported + 1 ) // ProfileNotFound may not be there
    status = (Gdiplus::Status)( Gdiplus::Status::PropertyNotSupported + 2 ); // gives last error (INVALID STATUS CODE)

  return statuses[ status ];
}

struct ImageEncoders
{
private:
  UINT byteSize;  // byteSize of encoders on system
  UINT NumberOfEncoders; // number of encoders on system
  ImageCodecInfo* imageCodecs;

public:
  enum ImageFormat { BMP, JPG, GIF, TIF, PNG };
  ImageEncoders()
  {
    // How many encoders do we have on the system?
    Gdiplus::GetImageEncodersSize( &NumberOfEncoders, &byteSize );
    if( !byteSize || !NumberOfEncoders )
    {
      error( TEXT( "ERROR: There are no image encoders available, num=%d, size=%d" ),
        NumberOfEncoders, byteSize );
      return;
    }

    // Allocate space to get the ImageCodeInfo descriptor for each codec.
    imageCodecs = ( ImageCodecInfo* )malloc( byteSize );
    Gdiplus::GetImageEncoders( NumberOfEncoders, byteSize, imageCodecs );

    wprintf( TEXT( "CODECS:\n" ) );
    // Print the codecs we know
    for( int i = 0; i < NumberOfEncoders; i++ )
    {
      wprintf( TEXT( "  * Codec %d = Ext:%s Description:%s\n" ),
        i, imageCodecs[i].FilenameExtension, imageCodecs[i].FormatDescription );
    }
  }

  // File types lists look like *.jpg;*.jpeg;*.jfif
  bool InFileTypesList( const TCHAR* ext, const TCHAR* filetypesList )
  {
    TCHAR* dup = wcsdup( filetypesList ); // We have to form a writeable copy of the FileTypesList
    TCHAR* delimiters = TEXT( "*.;" );
    TCHAR* tok = wcstok( dup, delimiters ); // 1st call is on dup, subsequent on NULL.
    // So we want this call outside the while loop anyway.
    bool in = 0;
    do
    {
      if( ! wcsicmp( ext, tok ) )
        in = 1;
      else  // Pull the next token
        tok = wcstok( NULL, delimiters ); // wcstok retains state, so you pass NULL to use last tokenized string
    } while( tok && !in );
    free( dup ); // release the manipulatable duplicate.
    return in;
  }

  CLSID GetCLSIDForExtension( const TCHAR* ext )
  {
    CLSID clsid = CLSID_NULL; // Start with assuming invalid clsid.

    // Use a case-insensitive comparison
    for( int i = 0; i < NumberOfEncoders; i++ )
    {
      if( InFileTypesList( ext, imageCodecs[ i ].FilenameExtension ) )
      {
        wprintf( TEXT("%s is type %s\n"), ext, imageCodecs[i].FormatDescription );
        clsid = imageCodecs[ i ].Clsid; // Found a CLSID for this extension
        break;
      }
    }

    return clsid;
  }

  CLSID GetCLSIDByMime( const TCHAR* mimetype )
  {
    CLSID clsid = CLSID_NULL;
    for( int i = 0; i < NumberOfEncoders; i++ )
    {
      // Straight comparison with listed mime type.
      if( !wcsicmp( mimetype, imageCodecs[ i ].MimeType ) )
      {
        clsid = imageCodecs[ i ].Clsid;
        break;
      }
    }
    return clsid;
  }

  ~ImageEncoders()
  {
    free( imageCodecs );
  }

  static bool Save( Image* im, TCHAR* filename )
  {
    ImageEncoders encoders;

    // Extract the extension
    TCHAR* dotLocation = wcsrchr( filename, TEXT('.') );
    if( dotLocation ) // found.
    {
      CLSID clsid = encoders.GetCLSIDForExtension( dotLocation+1 );
      if( clsid != CLSID_NULL )
      {
        Gdiplus::Status status = im->Save( filename, &clsid );
        if( status != Gdiplus::Status::Ok )
        {
          error( TEXT( "ImageEncoders::Save( %s ): Failed to save: %s" ), filename, GetStatusString( status ) );
          return 0;
        }
        else
          wprintf( TEXT( "%s saved successfully\n" ), filename );
        return 1;
      }
    }

    error( TEXT( "ImageEncoders::Save( %s ): Failed to save; invalid extension" ), filename );
    return 0;
  }

};


LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
  HDC hdc;
  PAINTSTRUCT ps;

  switch( message )
  {
    case WM_PAINT:
    {
      // "Start painting":  The HDC "handle to a device context"
      // is the 'surface' on which you draw.
      // You don't draw directly to a window. Rather you draw to a "device context".
      // The reason its this way is it makes it so you can draw to ANY SURFACE.
      hdc = BeginPaint( hWnd, &ps );

      #pragma region painting code
      // Create a Graphics object for our window's hdc
      Graphics g( hdc );

      // Create a pen.
      Pen bluePen( Color( 128, 0, 0, 255 ) );
      bluePen.SetWidth( 8.0 );

      g.DrawLine( &bluePen, 0, 0, 100, 100 );
      g.DrawEllipse( &bluePen, 0, 0, 40, 40 );
      g.DrawEllipse( &bluePen, 0, 0, 50, 50 );

      SolidBrush blueBrush( Color( 120, 0, 0, 255 ) );
      g.FillRectangle( &blueBrush, 60, 60, 190, 180 );

      SolidBrush redBrush( Color( 123, 255, 0, 0 ) );
      Font arialFont( TEXT( "Arial" ), 12.0 );
      PointF pTextPos( 20, 20 );

      g.DrawString( TEXT( "This is GDI+!" ),
        strlen( "This is GDI+!" ),
        &arialFont, pTextPos, &redBrush );
      g.FillRectangle( &redBrush, 30, 30, 100, 180 );

      TCHAR* imageFilename = TEXT( "picture.jpg" );
      Image *im = new Image( imageFilename );
      if( im->GetLastStatus() != Gdiplus::Ok )
      {
        error( TEXT( "Image `%s` not provided, please copy one into the src folder" ), imageFilename );
        system( "start ." ); // opens current folder in windows explorer
      }
      else
      {
        g.DrawImage( im, 50.f, 50.f );

        // Test saving as PNG and JPG
        ImageEncoders::Save( im, TEXT( "COPY.png" ) );
        ImageEncoders::Save( im, TEXT( "COPY.jpg" ) );
      }
      #pragma endregion
      // "Wrap it up"
      EndPaint( hWnd, &ps );
    }
    return 0;

    case WM_KEYDOWN:
      switch( wParam )
      {
        case VK_ESCAPE:
          PostQuitMessage( 0 );
          break;
      }
      return 0;

    case WM_DESTROY:
      PostQuitMessage( 0 );
      return 0;

    default:
      return DefWindowProc( hWnd, message, wParam, lParam );
  }
} // WndProc
Loop invariant
Given a data structure called STRUCTURE and an algorithm called ALGORITHM There’s a property that is true of STRUCTURE (the structure we are operating on) on every loop of the ALGORITHM, even as it runs.