Welcome to HBH! If you had an account on hellboundhacker.org you will need to reset your password using the Lost Password system before you will be able to login.

Windows GUI C/C++


Windows GUI C/C++

By lukem_95 avatarlukem_95 | 7982 Reads |
0     0

Written by Lukem_95 for HellboundHackers.org ONLY

Not to be reused without credit and link to this page.

I am not responsible for anything you use this tutorial to create…

#####################################

  1. What is GUI? GUI stands for Graphical User Interface, and this is basicly a program that has a window, instead of just the bog standard command line of most C apps.

I will be working with Bloodsheds Dev-C++, available from http://www.bloodshed.net.

OK, lets begin:

Open your compiler and select Windows Application from the startup screen (Not Command Application). This should bring up a source with the basic shell already constructed.

Something very similar to…


#include <windows.h>

/* Declare Windows procedure */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/* Make the class name into a global variable */ char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)

{ HWND hwnd; /* This is the handle for our window / MSG messages; / Here messages to the application are saved / WNDCLASSEX wincl; / Data structure for the windowclass */

/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);

/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;                 /* No menu */
wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
wincl.cbWndExtra = 0;                      /* structure or the window instance */
/* Use Windows&#39;s default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
    return 0;

/* The class is registered, let&#39;s create the program*/
hwnd = CreateWindowEx (
       0,                   /* Extended possibilites for variation */
       szClassName,         /* Classname */
       &quot;Windows App&quot;,       /* Title Text */
       WS_OVERLAPPEDWINDOW, /* default window */
       CW_USEDEFAULT,       /* Windows decides the position */
       CW_USEDEFAULT,       /* where the window ends up on the screen */
       544,                 /* The programs width */
       375,                 /* and height in pixels */
       HWND_DESKTOP,        /* The window is a child-window to desktop */
       NULL,                /* No menu */
       hThisInstance,       /* Program Instance handler */
       NULL                 /* No Window Creation data */
       );

/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);

/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
    /* Translate virtual-key messages into character messages */
    TranslateMessage(&messages);
    /* Send message to WindowProcedure */
    DispatchMessage(&messages);
}

/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;

}

/* This function is called by the Windows function DispatchMessage() */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) /* handle the messages / { case WM_DESTROY: PostQuitMessage (0); / send a WM_QUIT to the message queue / break; default: / for messages that we don't deal with */ return DefWindowProc (hwnd, message, wParam, lParam); }

return 0;

}

As you can see, all nicely commented already.

Looks confusing though huh? Yup well especially if you've NEVER used GUI before, you will be probably thinking something along the lines of "WTF?!?". :P

Lets explain it then shall we… (NOTE: i don't understand 100% every part of this code, and nor will most people, just how to use it.)

OK, well im asuming you know BASIC C atleast here, so i don't need to go over headers etc…

our first chunk:


#include <windows.h>

/* Declare Windows procedure */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/* Make the class name into a global variable */ char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)

Well… Line 1 declares the windows.h header, necessary for system() calls, the GUI structure and most of the functions you will need for GUI programming on a windows box.

The "LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);" line declares that the window will send data back to the body of the program, and that it will be a standard windows "window" :p

now we get to the registering the window and the application classname:


char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)

The "szClassName" is just a unique name for the window's "class", it could be anything you wish, although i tend to leave it as WindowsApp cos im lazy.

The "WINAPI" bit is setting up the application, to register it with Windows so the application can run.

It declares the instance name for the program, an argument name, for handling messages and also an empty integer declaration, this is for identifying excess bytes of memory, and dealing with it (NOTE: it doesn't have to be "nFunsterStil", that is something Dev-C++ used so it is easy to identify who uses their code :))

Now where onto declaring our actuall window and the style elements:


{ HWND hwnd; /* This is the handle for our window / MSG messages; / Here messages to the application are saved / WNDCLASSEX wincl; / Data structure for the windowclass */

/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);

/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;                 /* No menu */
wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
wincl.cbWndExtra = 0;                      /* structure or the window instance */
/* Use Windows&#39;s default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
    return 0;

This is the body of the WINAPI int function…

it starts by creating a handler for the window, the message handler, so it can process data such as mouseclicks or menu items, and a datastructure, so you can link text boxes etc back to the window.

The next little section just links the elements of the actual main window to the overall WINAPI elements.

Now this is the fun part, where you can edit the window style etc…


/* Use default icon and mouse-pointer / wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; / No menu / wincl.cbClsExtra = 0; / No extra bytes after the window class / wincl.cbWndExtra = 0; / structure or the window instance / / Use Windows's default color as the background of the window */ wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

This is pretty easy to follow, it declares each element of the window, and assigns the default Windows style to it, editing it is not hard, but requires an additional two files. I will cover this slightly later on in this tutorial.

Onto the next snippet:


/* Register the window class, and if it fails quit the program */ if (!RegisterClassEx (&wincl)) return 0;

/* The class is registered, let&#39;s create the program*/
hwnd = CreateWindowEx (
       0,                   /* Extended possibilites for variation */
       szClassName,         /* Classname */
       &quot;Windows App&quot;,       /* Title Text */
       WS_OVERLAPPEDWINDOW, /* default window */
       CW_USEDEFAULT,       /* Windows decides the position */
       CW_USEDEFAULT,       /* where the window ends up on the screen */
       544,                 /* The programs width */
       375,                 /* and height in pixels */
       HWND_DESKTOP,        /* The window is a child-window to desktop */
       NULL,                /* No menu */
       hThisInstance,       /* Program Instance handler */
       NULL                 /* No Window Creation data */
       );

/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);

The top bit of code here deals with the error's when registering the default window.

"if (!RegisterClassEx (&wincl))" when broken down says "if RegisterClassEx() returns false when trying to register wincl".

You can edit this to display a message alerting you to the error when it fails by adding the line:


MessageBox(hwnd, "Window could not be registered!", "Error!", MB_OK | MB_ICONINFORMATION); // Error popup

before the "return 0;". This creates a popup with a message (see if you can work out how to change what it says lol… its really not hard).

Ok… now the final bit of this chunk, some more asthetical elements of the window…


/* The class is registered, let&#39;s create the program*/
hwnd = CreateWindowEx (
       0,                   /* Extended possibilites for variation */
       szClassName,         /* Classname */
       &quot;AppTitle&quot;,       /* Title Text */
       WS_OVERLAPPEDWINDOW, /* default window */
       CW_USEDEFAULT,       /* Windows decides the position */
       CW_USEDEFAULT,       /* where the window ends up on the screen */
       544,                 /* The programs width */
       375,                 /* and height in pixels */
       HWND_DESKTOP,        /* The window is a child-window to desktop */
       NULL,                /* No menu */
       hThisInstance,       /* Program Instance handler */
       NULL                 /* No Window Creation data */
       );

Again pretty obvious, the comments provided tell all really, and although it says /No Menu/, this can be edited further up, in the other style part, without any change to the /No Menu/ bit (yes i know /**/ is a comment, but i meant the code before it).

This code overall just creates the main window.

The final little bit just makes the window visible to the user, if you commented it out you would essentially have a very poor silent application (if you were making a trojan etc, although you would need some additional code to hide i from Task Manager, i may post it at the end if i feel nice).

So now onto the message loop, one of the most important parts of out code, this is what handles ALL the input, whether thats keys being pressed, messages sent internally such as minimize and close, alt+f4, or mouse clicks:


/* Run the message loop. It will run until GetMessage() returns 0 / while (GetMessage (&messages, NULL, 0, 0)) { / Translate virtual-key messages into character messages / TranslateMessage(&messages); / Send message to WindowProcedure */ DispatchMessage(&messages); }

/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;

}

/* This function is called by the Windows function DispatchMessage() */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) /* handle the messages / { case WM_DESTROY: PostQuitMessage (0); / send a WM_QUIT to the message queue / break; default: / for messages that we don't deal with */ return DefWindowProc (hwnd, message, wParam, lParam); }

return 0;

}

This creates a while() loop, running constantly while the program is active, looking for any user input.

It then passes the input through a switch() statement, searching for a match. Any additional messages you add will need to be put into the switch() statement.

  1. Now for the fun bit… editing and creating your own stuff…

We will start by making a basic menu:

Ok, first off you need to create a header file for your resources, so goto file>new>source file and then save it as "res.h" (or any name you feel like really).

We also need a resource file, (.rc), to handle the identifiers for all our items. So add another source file and this time save it as "res.rc".

This is the basic setup for nearly all GUI apps.

Ok now were gonna add our basic menu, open up the res.rc resource file and type:


#include "res.h"

/Resource script for my first GUI file - tut by Lukem_95/

IDR_MENU MENU BEGIN POPUP "&File" BEGIN MENUITEM "&About", ID_FILE_ABOUT MENUITEM "E&xit", ID_FILE_EXIT END

POPUP &quot;&Edit&quot;
BEGIN
// Insert menu here :p
END

POPUP &quot;&Links&quot;
BEGIN
    MENUITEM &quot;&Visit Website&quot;, ID_LINK_WEBSITE
    MENUITEM &quot;G&oogle.com&quot;, ID_LINK_GOOGLE
END

END

You can change this to whatever you want, but if you do, make sure you change the ID__ bit to something of the same format (for ease of use).

What that does is create a basic menu, the syntax is extremely easy to learn to define a menu use the ID_YOURID MENU tag, then BEGIN //Content here END.

By putting a & infront of the letter, it creates a hotkey (the same as visual basic).

POPUP is the menu name that is shown always, then the MENUITEM's are the bits displayed when you hover/click on the popup bit.

save that and open up your header file ("res.h") and type:


#define IDR_MENU 101 #define IDC_MAIN_EDIT 102

// Menu ID's #define ID_FILE_EXIT 9001 #define ID_LINK_WEBSITE 9002 #define ID_LINK_GOOGLE 9003 #define ID_FILE_ABOUT 9004

You can use any ID, but i like to format it like above, cos its how i learned… (theForger's WIN32 API Tutorial).

and thats about it for the resource files at the moment, thats your basic menu, now lets make it display on your window shall we?

Find this line: "wincl.lpszMenuName = NULL;" and simply change it to: "MAKEINTRESOURCE(IDR_MENU);"

This just says get IDR_MENU from my resource file.

now onto editing the message loop, insert this code anywhere in the loop ( i assume you know hwto use a switch(), if not GOOGLE IT!):


case WM_COMMAND: switch(LOWORD(wParam)) { case ID_FILE_EXIT: // When user clicks exit… exit! PostMessage(hwnd, WM_CLOSE, 0, 0); break; case ID_LINK_GOOGLE: ShellExecute(NULL,"open","http:\\www.google.com",NULL,NULL,SW_MAXIMIZE); break; case ID_LINK_WEBSITE: { ShellExecute(NULL,"open","http:\\www.hellboundhackers.org",NULL,NULL,SW_MAXIMIZE); } break; case ID_FILE_ABOUT: // Creates messagebox with about info MessageBox(hwnd, "Made using Lukem_95's Tutorial on HBH", "About", MB_OK | MB_ICONINFORMATION); break; } break; case WM_CLOSE: DestroyWindow(hwnd); break;

Feel free to edit what it does, but thats the basic shell of it, easy to follow, in fact BASIC C lol

so, you have a basic program with a menu if you compile am i right??

not much good. (NOTE: you may have to goto project>options and tell it to include your .rc file when compiling, it also has a lot of cool options like editing the version n stuff).

OK, well i think maybe a custom icon is in order, then well get onto populating your program.

open up your rc file and type "IDI_ICON ICON "test.ico"" at the bottom. replacing test icon with the path to the icon you want.

then open your res.h header and create an ID for IDI_ICON. you should know what to do by now.

Now back in your main .CPP file, lets edit it so your icon will show up.

find:

wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);

and replace with


wincl.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON)); // Icon on the file browser
wincl.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, 0); // Icon

simple code, it tells it to load the icon from the path, and apply it to the icon in the file browser and in the top left corner.

  1. Time to populate!

To add things to the main window, you use the WM_CREATE message, like in this example:


case WM_CREATE:
{
    HFONT hfDefault;
    HWND hEdit;

    hEdit = CreateWindowEx( // Creates the editable text area
    WS_EX_CLIENTEDGE,
    &quot;EDIT&quot;, //type
    &quot;A&quot;, //Default text
    WS_CHILD | WS_VISIBLE/* | WS_HSCROLL | WS_VSCROLL | ES_MULTILINE*/, //Options
    150, // position - X axis
    25, // position - Y axis
    100, // Size - Length
    25, // Size - Height
    hwnd, // Child of...
    (HMENU)IDC_MAIN_EDIT, // Menu&#39;s
    GetModuleHandle(NULL), // Instance Handler
    NULL
    );
    if(hEdit == NULL)
        MessageBox(hwnd, &quot;Could not create edit box.&quot;, &quot;Error&quot;, MB_OK | MB_ICONERROR);

    //hfDefault = GetStockObject(DEFAULT_GUI_FONT); // Errors...
    SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
}
break;

This will create a very simple edit box, i have commented it so it will be fairly easy for you to edit it and make your own.

I wont go into too much detail here, as im not the most experienced perso ever, but ill list some commands and things you can do to improve your program.

Message box:


// char mbMessage[] = "Lukem_95 pwnZ! lol"; // Message box content //char mbTitle[] = "Title here"; // Message Box Title //MessageBox(hwnd, mbMessage, mbTitle, MB_OK | MB_ICONINFORMATION);

at the top of your script, if you type "#define WIN32_LEAN_AND_MEAN" it will compile much faster, and your app will use much less ram, the only thing is, if it wont compile, then you will need to comment it out, it works by removing some of the includes from windows.h

some messages:

WM_LBUTTon<i></i>click

left mouse button down

WM_RBUTTon<i></i>click

right mouse button down

WM_SIZE

resize window

WM_CLOSE

click [x] or press ctrl+F4

And finally… a script for a notepad style app… without the save function, so if anyone fancies building that in and posting i'd appreciate lol, i cant be bothered!


#include <windows.h> #include "resource.h"

/* Declare Windows procedure */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/* Make the class name into a global variable */ char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)

{ HWND hwnd; /* This is the handle for our window / MSG messages; / Here messages to the application are saved / WNDCLASSEX wincl; / Data structure for the windowclass */

/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);

/* Mouse icons and Icons */
wincl.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON)); // Icon on the file browser
wincl.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, 0); // Icon
wincl.hCursor = LoadCursor (NULL, IDC_ARROW); // Default Cursor
wincl.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);                 /* Menu */
wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
wincl.cbWndExtra = 0;                      /* structure or the window instance */
/* Use Windows&#39;s default color as the background of the window */
wincl.hbrBackground = (HBRUSH)(COLOR_3DFACE+4);// Black! default is -&gt; (HBRUSH) COLOR_BACKGROUND;

/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
    return 0;

/* The class is registered, let&#39;s create the program*/
hwnd = CreateWindowEx (
       0,                   /* Extended possibilites for variation */
       szClassName,         /* Classname */
       &quot;.::Lukem_95 Presents... Notepad lol::.&quot;,       /* Title Text */
       WS_OVERLAPPEDWINDOW, /* default window */
       CW_USEDEFAULT,       /* Windows decides the position */
       CW_USEDEFAULT,       /* where the window ends up on the screen */
       544,                 /* The programs width */
       375,                 /* and height in pixels */
       HWND_DESKTOP,        /* The window is a child-window to desktop */
       NULL,                /* No menu */
       hThisInstance,       /* Program Instance handler */
       NULL                 /* No Window Creation data */
       );

/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);


/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
    /* Translate virtual-key messages into character messages */
    TranslateMessage(&messages);
    /* Send message to WindowProcedure */
    DispatchMessage(&messages);
}

/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;

}

/* This function is called by the Windows function DispatchMessage() */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) /* handle the messages */ { case WM_CREATE: { HFONT hfDefault; HWND hEdit;

    hEdit = CreateWindowEx( // Creates the editable text area
    WS_EX_CLIENTEDGE,
    &quot;EDIT&quot;, //type
    &quot;A&quot;, //Default text
    WS_CHILD | WS_VISIBLE/* | WS_HSCROLL | WS_VSCROLL | ES_MULTILINE*/, //Options
    150, // position - X axis
    25, // position - Y axis
    100, // Size - Length
    25, // Size - Height
    hwnd, // Child of...
    (HMENU)IDC_MAIN_EDIT, // Menu&#39;s
    GetModuleHandle(NULL), // Instance Handler
    NULL
    );
    if(hEdit == NULL)
        MessageBox(hwnd, &quot;Could not create edit box.&quot;, &quot;Error&quot;, MB_OK | MB_ICONERROR);

    //hfDefault = GetStockObject(DEFAULT_GUI_FONT); // Errors...
    SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
}
break;
case WM_SIZE:
{
    HWND hEdit;
    RECT rcClient;

    GetClientRect(hwnd, &rcClient);

    hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
    SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
}
break; //Size
case WM_COMMAND:
        switch(LOWORD(wParam))
        {
            case ID_FILE_EXIT: // When user clicks exit... exit!
                 PostMessage(hwnd, WM_CLOSE, 0, 0);
            break;
            case ID_LINK_GOOGLE:
                 ShellExecute(NULL,&quot;open&quot;,&quot;http:&#92;&#92;www.google.com&quot;,NULL,NULL,SW_MAXIMIZE);
            break;
            case ID_LINK_WEBSITE:
                 {
                 ShellExecute(NULL,&quot;open&quot;,&quot;http:&#92;&#92;www.hellboundhackers.org&quot;,NULL,NULL,SW_MAXIMIZE);
                 }
            break;
            case ID_FILE_ABOUT:
                 // Creates messagebox with about info
                 MessageBox(hwnd, &quot;Created By: LuKeM_95&#92;n&#92;nFor: HBH Tutorial&quot;, &quot;About&quot;, MB_OK | MB_ICONINFORMATION);
                 break;
        }
    break;
    case WM_DESTROY:
        PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
    break;
    case WM_CLOSE:
        DestroyWindow(hwnd);
    break;
    default:                      /* for messages that we don&#39;t deal with */
        return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;

}

You need the same .rc and .h files as before to compile it.

Thanks for reading! Lukem_95

Gr33tZ - Ac1d, Tomo_X

Comments
lukem_95's avatar
lukem_95 17 years ago

Oh, be careful to add backslashes when compiling… for newlines etc, it removes em for security here :happy:

ghost's avatar
ghost 17 years ago

nice job im currently learning GUI programming with C++ and yeh it has been proving challenging but still awesome, anyway once again good job

ghost's avatar
ghost 17 years ago

very nice man thanks! i have been trying to find some time to find tutorial such as yours that actually describes each function of the premade GUI C code as above. Thanks alot, and 5 / 5.

ghost's avatar
ghost 17 years ago

I've been meaning to try out c++ GUI programming for a while now, and this article has certainly helped me on my way. Awesome Job.

ghost's avatar
ghost 17 years ago

Oh god >< This is why I use WxWidgets.

Mad Props man :)

ghost's avatar
ghost 17 years ago

nice one, but you forgot to mention that without handling WM_PAINT messages the window cant be moved around :/. still very good though :)

ghost's avatar
ghost 17 years ago

yes, very nice dude. This is the kind of articles HBH needs, not those "Introduction to being a pro-1337 n00bie SK!"

lukem_95's avatar
lukem_95 17 years ago

Thankyou, i can't believe i have 7 awesome ratings!

And @ mr noob, maybe you could write a follow up on more advanced funtions, as im not competant on WM_PAINT, and in my program, i can move it without declaring it.

ghost's avatar
ghost 17 years ago

nice articlr

ghost's avatar
ghost 17 years ago

btw you got 9 awsomes now

richohealey's avatar
richohealey 17 years ago

yeah this shit is shit hot. will be 11 when i post!

ghost's avatar
ghost 17 years ago

Very good… Though I'm still never going to learn it… wxWidgets kick ass :happy:

ghost's avatar
ghost 17 years ago

Wow, nicely done! I too had been looking for a decent article on working with GUIs in C/C++! Thanks! =)

ghost's avatar
ghost 17 years ago

A+

ghost's avatar
ghost 17 years ago

A+ indeed. thx mate! for a nice read

lukem_95's avatar
lukem_95 17 years ago

:D thanks everyone

lukem_95's avatar
lukem_95 17 years ago

im thinking of doing V2… with controls, system tray, music etc? would anyone be interested?

ghost's avatar
ghost 17 years ago

heh @lukem never mind about WM_PAINT i just realised you use a different set of instructions to draw stuff from me :P

ghost's avatar
ghost 16 years ago

dude you pwnd this kickass tut i wish i would have came here to learn i had to figur it out formyself >.<