Posts mit dem Label Windows werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Windows werden angezeigt. Alle Posts anzeigen

Samstag, 26. März 2011

Exception Handling - Inform your users!

Hello everyone!

This article will show you methods to inform the user that something has happened in the program which caused an exception that was not handled by the program. It will also teach you how to use the values you will get and display some more information the user can then submit to you.

First we should know what happens if an exception is thrown. The operating system now aims to find a handler which tells what to do now. In order to find such a handler the system has a fixed order to search. It will start with the vectored exception handlers (added for example using AddVectoredExceptionHandler). If no handler was found there it will continue and in each frame of the stack it will examine all the frame based exception handlers (try - catch, __try - __except). If no handler suited the exception thrown it will then have a look if a top level exception handler is registered (using SetUnhandledExceptionFilter). If that fails too you will get a window "XY has stopped working" with the commonly known options. There is actually one exception from that behavior: When a debugger is attached. In this case the debugger is automatically installed as the top level exception handler and you cannot change it. Using various settings you can even intercept all of the above mentioned handlers and directly pass every exception to the debugger.

Well, now how could we get informed that an exception happened that was not properly handled? Using AddVectoredExceptionHandler is not a good idea because every exception that happened will be interpreted as if it was not handled. Thats not what we try to achieve. Installing a frame on top of every thread that gets started and handling every type of exception there is possible but to much work. Also threads started by external components maybe dont act like that and exceptions caused by them wont be recognized.

The response is using SetUnhandledExceptionFilter. This function lets us register a function that is called if all other handlers failed. As this is the last resort we can be sure that no one "cared" about that exception and that it will lead to an unwanted program termination if nothing is done now. The usage of that function is very easy. All it wants is a pointer to a function which has a special format. It then returns a pointer to the function that was installed before our call so we could reset it if we dont need to handle the exceptions anymore. So to test that we make a simple program:
#include <Windows.h>

LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
 MessageBox(0, "An exception occured which wasnt handled!", "Error!", MB_OK);
 return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
 SetUnhandledExceptionFilter(UnhandledException);

 char* ptr = NULL;
 *ptr = 'a';
}

The return value of our function indicates what the operating system should do next. Returning EXCEPTION_CONTINUE_HANDLER instructs it to execute the handler for that exception. On the top level this actually means that it will directly call ExitProcess. If you run the above code (please make sure you are not attaching any debugger) you will get the messagebox (unless you are in kernel mode) and the application will terminate.

Now lets experiment with that. First we will look if the function also gets called if we surround the bad code with try - catch(...). First maybe think if you can figure out the response yourself.
#include <Windows.h>

LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
 MessageBox(0, "An exception occured which wasnt handled!", "Error!", MB_OK);
 return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
 SetUnhandledExceptionFilter(UnhandledException);

 try
 {
  char* ptr = NULL;
  *ptr = 'a';
 }
 catch(...)
 {

 }
}

After running the code we know: It gets called! Maybe that is surprising you. If so have a look at the following code:
#include <Windows.h>

LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
 MessageBox(0, "An exception occured which wasnt handled!", "Error!", MB_OK);
 return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
 SetUnhandledExceptionFilter(UnhandledException);

 __try
 {
  char* ptr = NULL;
  *ptr = 'a';
 }
 __except(EXCEPTION_EXECUTE_HANDLER)
 {

 }
}

Wait, now it is not called?! But why? The answer is pretty simple: There are two main types of exceptions. The first type are exceptions that are thrown using the keyword 'throw'. They are called C++-exceptions. These exceptions get caught using the try-catch statement. The other type are exceptions that are thrown by the operating system in response of faults that happened. These are called SEH-exceptions (structed exception handling). To catch such an exception there must be a frame which catches exceptions using __try - __except. We see the EXCEPTION_EXECUTE_HANDLER here again. In this case the executed "handler" is the part in the scope after __except.

As dereferencing the NULL-Pointer and assigning a value to it in user mode is not allowed the operating system indicates a fault and throws a SEH-exception. Those exceptions cannot be handled by try - catch statements. Therefore in the first code the exception is passed to our function. But in the second code the exception is caught and the program can continue so our function is not called.

Well, now our messagebox does not really contain a lot of information. A user which sees that message wont have an idea what to do and if he submits it to you this wont help at all. So providing some more information would be helpful. So we'll use the parameter our exception handler receives to find additional information about the exception which we can show to the user. The most important things one should now are the following two:
What happened?
Where did it happen?

The answer to both questions lies inside the exceptionInfo parameter. And here is how we can access it:
#include <Windows.h>
#include <iostream>

LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
 char message[255];
 sprintf_s<255>(message, 
  "An exception occured which wasnt handled!\nCode: 0x%08X\nAddress: 0x%08X", 
  exceptionInfo->ExceptionRecord->ExceptionCode,
  exceptionInfo->ExceptionRecord->ExceptionAddress
 );
 MessageBox(0, message, "Error!", MB_OK);
 return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
 SetUnhandledExceptionFilter(UnhandledException);

 char* ptr = NULL;
 *ptr = 'a';
}

I think this is pretty self-explaining. Though there is one major problem with the exception address. If our binary uses ASLR (Address Space Layout Randomization) its base address will start at a random address at every launch. Therefore the address is completely useless for us as we dont know where the binary starts. To solve that problem we could print the start and end address for every module loaded into the message box which would allow us to exactly determine in which module at which offset the exception happened or we just print the start of the main module and the offset from there. The second version is less informative because if the exception didnt happen in the main module we again have an offset which is not really useful. But anyway, we will use the second approach as we focus on our executable.

#include <Windows.h>
#include <iostream>

LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
 DWORD codeBase = (DWORD)GetModuleHandle(NULL);
 char message[255];
 sprintf_s<255>(message, 
  "An exception occured which wasnt handled!\nCode: 0x%08X\nOffset: 0x%08X\nCodebase: 0x%08X", 
  exceptionInfo->ExceptionRecord->ExceptionCode,
  (DWORD)exceptionInfo->ExceptionRecord->ExceptionAddress - codeBase,
  codeBase
 );
 MessageBox(0, message, "Error!", MB_OK);
 return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
 SetUnhandledExceptionFilter(UnhandledException);

 char* ptr = NULL;
 *ptr = 'a';
}

Now we have an offset which can be used to determine which instruction caused the exception. If you start google and search for "Exception code 0xC0000005" you will find that this stands for an access violation. Wouldnt it be nice to show EXCEPTION_ACCESS_VIOLATION instead of 0xC0000005? There is a simple way doing that using a little macro that converts the predefined codes into a friendlier form:
#include <Windows.h>
#include <iostream>

#define EXCEPTION_CASE(code) \
 case code: \
  exceptionString = #code; \
  break

LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
 const char* exceptionString = NULL;
 switch(exceptionInfo->ExceptionRecord->ExceptionCode)
 {
 EXCEPTION_CASE(EXCEPTION_ACCESS_VIOLATION);
 EXCEPTION_CASE(EXCEPTION_DATATYPE_MISALIGNMENT);
 EXCEPTION_CASE(EXCEPTION_BREAKPOINT);
 EXCEPTION_CASE(EXCEPTION_SINGLE_STEP);
 EXCEPTION_CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
 EXCEPTION_CASE(EXCEPTION_FLT_DENORMAL_OPERAND);
 // add more cases...

 default:
  exceptionString = "Unknown exception";
  break;
 }

 DWORD codeBase = (DWORD)GetModuleHandle(NULL);
 char message[255];
 sprintf_s<255>(message, 
  "An exception occured which wasnt handled!\nCode: %s (0x%08X)\nOffset: 0x%08X\nCodebase: 0x%08X", 
  exceptionString,
  exceptionInfo->ExceptionRecord->ExceptionCode,
  (DWORD)exceptionInfo->ExceptionRecord->ExceptionAddress - codeBase,
  codeBase
 );
 MessageBox(0, message, "Error!", MB_OK);
 return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
 SetUnhandledExceptionFilter(UnhandledException);

 char* ptr = NULL;
 *ptr = 'a';
}

Now the user sees a better readable name for the exception code. Have a look at this article on MSDN to get a list with all defined exception codes that commonly occur: Article

Now lets change the main function to the following:
int main()
{
 SetUnhandledExceptionFilter(UnhandledException);

 throw "An error!";
}

Even if you defined all cases from the MSDN-article here you will get "Unknown exception (weird hex-number)". What does that number stand for? Maybe its a pointer to the string we have thrown? And beside that, why do we get such a huge offset? Our executable isn't that big! To answer the second question first: throw will actually be replaced by the compiler to a internal function call to CxxThrowException which then again calls RaiseException. The offset you get is the offset to RaiseException as this is considered the source of the exception and RaiseException lies inside the ntdll.dll which is loaded in high memory regions. See the following extract from IDA Pro:
.text:7DE80000 ; File Name   : C:\Windows\System32\ntdll.dll
.text:7DE80000 ; Format      : Portable executable for 80386 (PE)
.text:7DE80000 ; Imagebase   : 7DE70000

To answer the first question try throwing different things. Throw an integer, throw nothing (just throw;), throw another string, ... . You will notice that the hex-number will always be the same (0xE06D7363). So obviously it has nothing to do with the content thrown. No, it denotes that the thrown exception was a C++ exception (remember, these are exceptions thrown by the programmer using throw). So every time you use throw you will get the code mentioned above. So we can extend our switch with that static code:
#include <Windows.h>
#include <iostream>

#define EXCEPTION_CASE(code) \
 case code: \
  exceptionString = #code; \
  break

LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
 const char* exceptionString = NULL;
 switch(exceptionInfo->ExceptionRecord->ExceptionCode)
 {
 EXCEPTION_CASE(EXCEPTION_ACCESS_VIOLATION);
 EXCEPTION_CASE(EXCEPTION_DATATYPE_MISALIGNMENT);
 EXCEPTION_CASE(EXCEPTION_BREAKPOINT);
 EXCEPTION_CASE(EXCEPTION_SINGLE_STEP);
 EXCEPTION_CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
 EXCEPTION_CASE(EXCEPTION_FLT_DENORMAL_OPERAND);
 // add more cases...

 case 0xE06D7363:
  exceptionString = "C++ exception (using throw)";
  break;

 default:
  exceptionString = "Unknown exception";
  break;
 }

 DWORD codeBase = (DWORD)GetModuleHandle(NULL);
 char message[255];
 sprintf_s<255>(message, 
  "An exception occured which wasnt handled!\nCode: %s (0x%08X)\nOffset: 0x%08X\nCodebase: 0x%08X", 
  exceptionString,
  exceptionInfo->ExceptionRecord->ExceptionCode,
  (DWORD)exceptionInfo->ExceptionRecord->ExceptionAddress - codeBase,
  codeBase
 );
 MessageBox(0, message, "Error!", MB_OK);
 return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
 SetUnhandledExceptionFilter(UnhandledException);

 throw "An error!";
}

So far those are the most important things you should now about displaying generic information about every type of exception. In upcoming articles we will have a look on how we can give more information which will require us to perform individual actions for each type of exception.

Thanks for reading and happy commenting
Yanick

Freitag, 25. März 2011

Dialog Controls explained - Part 1

Hello

In this series of articles i will describe you the usage of several common controls that are used together with windows. Here it actually doesn't matter if you are using a dialog resource and DialogBox to create the window or if you are doing it the manual way using CreateWindow for the main window and all its controls. All you need is just a HWND to that control you are interacting with. Tough in this article for now you can only see the source code that uses a dialog template to create the window. So if you are not using a dialog resource just stick to the part we are actually acting with the controls.

The base part of this project is an empty dialog with no controls on it and the following code that displays it:
#include <Windows.h>
#include "resource.h"

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;

 case WM_INITDIALOG:
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

Now lets start adding controls to it!


The common button control

Buttons are represented by the following window class: "Button" (pretty unexpected...)

We can drag & drop button from the toolbox onto our dialog:


The property bar in Visual Studio already gives you a lot of customization options. As every of them is described pretty well inside the property view i think its not really necessary to talk about them. If you are unsure about one just leave a comment!

Well, the most important thing buttons are for is handling clicks. Thus we should know what happens if we click on a button. This is rather simple. The button sends a WM_COMMAND message to its parent window setting wParam and lParam to appropriate values. Its like that:
HIWORD(wParam) = notification code = BN_CLICKED
LOWORD(wParam) = Control ID = IDC_BUTTON1 (for this button in my case)
lParam = Control handle = some value we dont know yet

So to handle a click from a button all you need to do is catching WM_COMMAND in the DialogProc (or WndProc if you are using a regular window) and interpret the values!

Thats an example code that handles the click on our button:
#include <Windows.h>
#include "resource.h"

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;

 case WM_INITDIALOG:
  return TRUE;

 case WM_COMMAND:
  {
   if(LOWORD(wParam) == IDC_BUTTON1)
   {
    if(HIWORD(wParam) == BN_CLICKED)
     MessageBox(0, "Button clicked!", "", MB_OK);
   }
  }
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

All we do is catching WM_COMMAND and then we compare if the ID is our button and if the code is BN_CLICKED. Thats pretty easy!

As a side note there are interesting styles for buttons defined in CommCtrl.h! For example the following code:
#include <windows.h>
#include "resource.h"
#include <commctrl.h>

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;

 case WM_INITDIALOG:
  {
   HWND hButton = GetDlgItem(hWindow, IDC_BUTTON1);
   // do something if hButton == NULL
   LONG oldStyle = GetWindowLongPtr(hButton, GWL_STYLE);
   oldStyle |= BS_SPLITBUTTON;
   SetWindowLongPtr(hButton, GWL_STYLE, oldStyle);
  }
  return TRUE;

 case WM_COMMAND:
  {
   if(LOWORD(wParam) == IDC_BUTTON1)
   {
    if(HIWORD(wParam) == BN_CLICKED)
     MessageBox(0, "Button clicked!", "", MB_OK);
   }
  }
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

Lets the button look like that:


but be aware: This is only available from Windows Vista on!

Another neat feature of buttons is that they can display images! This is done pretty easy. In the property page you can set the "Bitmap" property to true which will instruct the button to display a bitmap (of course only after we send BM_SETIMAGE). With that in mind the following code can be used to add the image to the button:
#include <windows.h>
#include "resource.h"
#include <commctrl.h>

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 static HBITMAP hButtonBackg = (HBITMAP)LoadImage(0, "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;

 case WM_INITDIALOG:
  {
   HWND hButton = GetDlgItem(hWindow, IDC_BUTTON1);
   // do something if hButton == NULL
   SendMessage(hButton, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hButtonBackg);
  }
  return TRUE;

 case WM_COMMAND:
  {
   if(LOWORD(wParam) == IDC_BUTTON1)
   {
    if(HIWORD(wParam) == BN_CLICKED)
     MessageBox(0, "Button clicked!", "", MB_OK);
   }
  }
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

And instead of text now there is an image being displayed (of course only if image.bmp exists in the current folder!). One might expect that setting the bitmap property inside the property page to false will hide the image on the button. But thats not true. That property more says "Only bitmap and no text". If you set Bitmap to false and send BM_SETIMAGE the text and the image will displayed organized on the button!

And a last nice feature of buttons (starting at Windows Vista) is that they can be used to elevate the current user level (pushing the application into administrator mode).

If you have windows vista the following code will put an UAC-Shield on the button (this wont handle putting the application into a higher state! It only displays the shield!)
#include <Windows.h>
#include "resource.h"
#include <commctrl.h>

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 static HBITMAP hButtonBackg = (HBITMAP)LoadImage(0, "image2.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;

 case WM_INITDIALOG:
  {
   HWND hButton = GetDlgItem(hWindow, IDC_BUTTON1);
   // do something if hButton == NULL
   SendMessage(hButton, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hButtonBackg);
   Button_SetElevationRequiredState(hButton, TRUE);
  }
  return TRUE;

 case WM_COMMAND:
  {
   if(LOWORD(wParam) == IDC_BUTTON1)
   {
    if(HIWORD(wParam) == BN_CLICKED)
     MessageBox(0, "Button clicked!", "", MB_OK);
   }
  }
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

Note that the other image we sent isnt displayed anymore!

More to come later...

Thanks for reading and happy commenting!
Yanick

Donnerstag, 24. März 2011

Getting static - Tips with static controls

Aloha

This article covers handling of static controls. Those controls are a bit nasty and need to be tweaked so they work correctly. Also it sometimes is not obvious that a control is a static control which we will see later!

The following code is based on the project created in this article. If you dont remember how interacting with controls works check out this article.

Our final application will load an image when a button is pressed and display it inside a picturebox. You maybe are wondering now where there is a static control involved because neither a button nor a picturebox is really static. But in fact a picturebox is considered a static control. To be clearer a picturebox is nothing more than a simple static control with a style that indicates that this control accepts bitmaps as background.

To start we drag a picturebox control on the dialog and we add a button. I renamed the button to IDB_LOADIMG and left the picturebox as it is. If you save now and open the resource.h you may see that there is only the IDB_LOADIMG and the ID from the picturebox is not present! Why?

Static controls by default are not listed and cannot be accessed. To change that you have to change the ID of every static control you create. This will immediatly add it to the resource.h. Ok, i renamed my picturebox control to IDC_PICBOX. To set the background of a static control you have to send a message to that control. This is done using the function SendMessage. The message to use is STM_SETIMAGE. So the code looks like that:
#include <Windows.h>
#include "resource.h"

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 static HWND hButtonLoad = NULL;
 static HWND hPicBox = NULL;
 static HBITMAP hBmp = (HBITMAP)LoadImage(NULL, "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;

 case WM_INITDIALOG:
  {
   hButtonLoad = GetDlgItem(hWindow, IDB_LOADIMG);
   hPicBox = GetDlgItem(hWindow, IDC_PICBOX);
   if(hButtonLoad == NULL || hPicBox == NULL)
   {
    MessageBox(hWindow, "Unable to retrieve controls! Closing....", "Error!", MB_OK);
    EndDialog(hWindow, 0);
    DestroyWindow(hWindow);
    return TRUE;
   }

   break;
  }
  return TRUE;

 case WM_COMMAND:
  {
   if(HIWORD(wParam) != BN_CLICKED) // we are only interested in clicks
    break;

   switch(LOWORD(wParam))
   {
   case IDB_LOADIMG:
    {
     SendMessage(hPicBox, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBmp);
     break;
    }
    break;
   }
  }
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

If you run this you need to make sure that an image called image.bmp is in the folder of the executable. LoadImage is used to load that image as a bitmap. The WPARAM of STM_SETIMAGE indicates which type of background we are sending and the LPARAM is in this case a handle to the bitmap.

When you compile this and run the application and press the button to load the image most likely you will see something like that:


Hey, where is our image?! The answer: Its not displayed at all! Why? Pretty simple: Have a look at the properties page of the picturebox control inside the dialog editor. You can find the column "type" which currently contains "Frame" (unless you have changed it). This tells the system that the control is just a frame. If you send an image to that control Windows will think "Wow, its nice he sends me an image, but actually im just a frame, i dont display images!". So we need to instruct the operating system that our control should accept bitmaps. We change the "Type" to "Bitmap". You may notice that the control now isnt scalable anymore. This is because it will automatically scale to fit the size of the image that gets loaded.

If we compile now and rerun the application after pressing the button the image gets displayed, in my case it looks like that:


Cool, isnt it? :)

Thanks for reading and cya
Yanick

Using a dialog - Using buttons & co.

Hi everyone

This article continues where the first article about dialogs ended. If you didn't read that so far you can do it here.

Important notice for users which do not use the paid version of Visual Studio:
Depending on the free editor you are using you maybe need to convert the source code a bit or move files. For example ResEdit creates a resource.h but you need to move it to your projects folder first
.

In the article linked above we have seen how we can show and destroy a dialog using a resource inside the executable and the function DialogBox. Now we want to let the user interact with controls on the dialog. In this example we will make a dialog that has a two buttons and an edit box where the user can enter text.

First we need to design our dialog. Please have a look at the properties tab in visual studio for the dialog and the children to customize them. Here is how i made mine look:


Now in order to identify controls on a dialog every control becomes its own ID. You can view this ID if you select the control and go to the properties tab. There you'll find the column "ID". It contains the name of the control. For my Flash Window button it looks like that:


This name will be important later. The Request text button has the ID IDB_REQTEXT and the edit control is named IDC_EDIT1. Thats all for the design. Now we can switch back to the code!

As all logic will be performed inside the DialogProc function so long all variables will be static ones inside that function. To retrieve handles (accessors) for the controls windows exposes the function GetDlgItem (which means "get item inside dialog") which searches all controls and looks if it matches the given ID. The usage of GetDlgItem is very simple. The first parameter is the dialog that should be searched and the second parameter is the ID (see above) of the control to search.

This results in the following code:
#include <windows.h>
#include "resource.h"

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 static HWND hButtonFlash = NULL;
 static HWND hButtonReq = NULL;
 static HWND hEdit1 = NULL;

 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;

 case WM_INITDIALOG:
  {
   hButtonFlash = GetDlgItem(hWindow, IDB_FLASH);
   hButtonReq = GetDlgItem(hWindow, IDB_REQTEXT);
   hEdit1 = GetDlgItem(hWindow, IDC_EDIT1);
   if(hButtonFlash == NULL || hButtonReq == NULL || hEdit1 == NULL)
   {
    MessageBox(hWindow, "Unable to retrieve controls! Closing....", "Error!", MB_OK);
    EndDialog(hWindow, 0);
    DestroyWindow(hWindow);
    return TRUE;
   }

   break;
  }
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

We are searching the codes as soon as the dialog is ready which is inside WM_INITDIALOG. We also check if we could get handles to all controls we need and if not we sadly need to terminate the application because they are essential!

Well, now, what happens if the user clicks on the flash button? In fact a message to its owner (which is the dialog) is sent indicating what happened. The ID of that message is WM_COMMAND. For controls of a dialog it has a special layout. The high word of wParam holds the type of command that is sent. The low word of wParam holds the ID of the control that sent the message and lParam holds a handle to that control. Using that we can easily determine if one of our buttons was pressed and also which one as you can see in this code:
#include <Windows.h>
#include "resource.h"

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 static HWND hButtonFlash = NULL;
 static HWND hButtonReq = NULL;
 static HWND hEdit1 = NULL;

 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;

 case WM_INITDIALOG:
  {
   hButtonFlash = GetDlgItem(hWindow, IDB_FLASH);
   hButtonReq = GetDlgItem(hWindow, IDB_REQTEXT);
   hEdit1 = GetDlgItem(hWindow, IDC_EDIT1);
   if(hButtonFlash == NULL || hButtonReq == NULL || hEdit1 == NULL)
   {
    MessageBox(hWindow, "Unable to retrieve controls! Closing....", "Error!", MB_OK);
    EndDialog(hWindow, 0);
    DestroyWindow(hWindow);
    return TRUE;
   }

   break;
  }
  return TRUE;

 case WM_COMMAND:
  {
   if(HIWORD(wParam) != BN_CLICKED) // we are only interested in clicks
    break;

   switch(LOWORD(wParam))
   {
   case IDB_FLASH:
    {
     FlashWindow(hWindow, TRUE);
     break;
    }
    break;
   case IDB_REQTEXT:
    {
     int textLen = GetWindowTextLength(hEdit1);
     if(textLen == 0)
      break;

     // We need to include the terminating 0, GetWindowTextLength does not count it!
     TCHAR* wndText = new TCHAR[textLen + 1];
     GetWindowText(hEdit1, wndText, textLen + 1);
     MessageBox(hWindow, wndText, "Info", MB_OK);
     delete [] wndText;
    }
    break;
   }
  }
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

There is one other important thing to say about WM_COMMAND. The high word of wParam which specifies the notification code is not different for every single type of notification that exists. Its only unique for each type of control. For example BN_CLICKED is defined as 0. There are other types of controls which also have the notification code defined which not really means that they were clicked. So always take the type of control that sent the notification into account, thats very important!

Thanks for reading and cheers
Yanick

Opening the Window - Creating a dialog!

Hello everyone!

In this article we will focus on how to easily create a basic layout for a window. It is using dialog templates stored as a resource inside an executable or DLL. It is often a lot of work to create a layout for a window just using the
CreateWindow
function is pretty a mess also because you cannot view directly how it will finally look. Having a WYSIWYG editor would be way easier! Interestingly there exists a simple way to code using such an editor. In order to achieve that you need to create the window from a resource which is embedded into the executable. This resource contains text that describes how the window should be led out. And the best thing is: There are free and paid editors for those files. Ill describe both, one with a free and one with a paid editor.

Users with a paid version of Visual Studio 
To add a dialog resource you do the following



This will show up a new dialog window that lets us select which type of resource to add. Obviously we will create a dialog resource!



The simplest is to just use Dialog. It will create a nice window and show it up in a new UI. There you can freely add controls, change properties of the window or the controls added.

When you are finished designing the window you can return to your project and you see that there are 2 new files. One is the resource.h which defines symbolic names for the resources and ProjectName.rc. This is the file which describes how resources are called inside the executable.


Users which have no paid version of Visual Studio 
There are free editors available to create a resource script (.rc) file and edit the contents. I think the best one is ResEdit. Its freely available and pretty easy to handle. When finished you will have a .rc file with a dialog resource included. You can drag that .rc file into your project and compile. It will be included into the executable. Thats it!

From now on everything is the same for the paid and the free version. 

Simply displaying the dialog is a very easy task. Windows offers us a function called DialogBox. This function expects parameters that specify where to find the dialog resource. Then it shows the dialog and returns when the dialog is destroyed. As usual also dialogs send messages to the application telling it that something interesting may have happened. So the code to show our dialog is pretty simple:
#include <Windows.h>
#include "resource.h" // users with ResEdit do not need that because they dont have it

// make sure visual styles are enabled
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;
 case WM_INITDIALOG:
  return TRUE;
 }

 return FALSE;
}

int main()
{
 // Users with ResEdit specify "Name of the resource" for the second param
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

The most complex is the DialogProc function. In opposite to regular message handlers it only returns a boolean. This boolean tells the operation system if our application has handled the message or not. The two messages that are important are WM_CLOSE and WM_INITDIALOG. The first message is sent when the user presses the close icon, the latter is sent when the dialog is loaded. In WM_INITDIALOG the return value indicates if the keyboard focus should be set to the control the operating system has chosen or not. This actually the recommended way.

In WM_CLOSE we first end the dialog using EndDialog and then destroy the window using DestroyWindow. The second parameter of EndDialog will be the value that DialogBox will return!

Thats it, we have made a nice window without much code!

Next step: here

Thanks for reading and greetings
Yanick

Enabling Visual Styles - Make it pretty!

Hello there

A lot of people ask me why in C++ the windows they create look that ugly while in C# or other .NET languages they look very nice. To illustrate what i mean look at the following images:
C++:


C#


The reason why this happens lies inside the manifest (or more exactly the application context). A .NET application automatically generates an application context that loads the Version 6 of the Microsoft.Windows.Common-Controls assembly instead of the default one which is Version 5. While Version 5 renders the common controls without any visual styles Version 6 uses the appropriate styles since Windows XP.

To achieve that you need to add a dependency inside the manifest and you need to ship it with your executable. Thats how the source code looks in my example application which is the way i prefer to ship the manifest with my application.
#include <windows.h>
#include "resource.h"

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 switch(uMsg)
 {
 case WM_CLOSE:
  EndDialog(hWindow, 0);
  DestroyWindow(hWindow);
  return TRUE;
 case WM_INITDIALOG:
  return TRUE;
 }

 return FALSE;
}

int main()
{
 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}

IDD_DIALOG1 is the numerical constant of a dialog resource embedded inside my executable.

Thanks for reading and im looking forward reading your comments!
Yanick