Simple WIN API Application

Pages: 12
Still...
Still what?

(2) What's the difference between WIN API and the projects you do in MSVC (dragging and dropping)


Read this post...

http://www.cplusplus.com/forum/windows/31963/


Now take an average bloke for example. A person who is merely struggling with C++ basics to intermediate, and try to get them to understand Windows API programming.

They'll punch the screen within 2 minutes. :)


How long have you been programming?

Win32 is a fairly advanced topic. I think an analogy applies here you might understand if you have any kind of math background. To be able to do/understand calculus you have to be very, very good at algebra. If you attempt to do caluclus without this algebra background you'll be punching the screen, wall, yourself, your buddies, etc., in two minutes.

I'm 58 and have been doing Win32 for twelve years. I started programming with main frame computers in Fortran in 1975. In the 80s and 90s I used basic and C. After 2000 I started with C++ and have experience with all the various class frameworks, and for my uses they are all in varying degrees unsatisfactory to me. I have found Win32 to be best for my projects. It wasn't created for beginners though. Petzold's Programming Windows books are the best way to learn. The target audience for Petzold's books were professional level C programmers. He stated that with that background one could become relatively proficient at Win32 in maybe 6 months; or 180 days if you used his books. So judge how you are doing by that yardstick. If you consider yourself to be a professional level C or C++ programmer you might learn it in 6 months. If your background is something less than that, figure longer. But don't talk trash about the technique because you've had your 1st three month course in console mode C++, and Win32 doesn't come in a couple days.
closed account (E60S216C)
(1) What does a troll mean?

(2) What's the difference between WIN API and the projects you do in MSVC (dragging and dropping)

(3) Why do I keep getting a win32 console even though I've created a window?


(1) A troll is a user or person whose attempt is to flame or disrupt a community of people on the internet or certain people with spamming, annoyance and flooding, usually accompanied by a false identity they use.

(2) Win API itself is the real GUI for Windows & programming. In MSVC it's made easy for you on purpose for people who can't write out the raw code to perform events using Windows API or people who don't feel like it..

(3) I don't know what you mean but you'll need a GUI sort of console application in order to use a programming language with a GUI interface and not a console application itself.

Hope I was some what helpful. I'm a total beginner though.... :(
Last edited on
helpmeagainANDagain:

I thought you didn't know any programming!

some random dude:

I mean the win32 console is still showing!

freddie1:

Thanks for the explanation, well I'm a student... I've covered C++ basics. I insist on doing the visuals with C++ and not C# for an unknown reason! C++ simply seems to be more elegant in every thing. I think I can do anything with C++ just if I learn how.
But thanks again, I didn't find the Petzold book at my university and in the biggest bookshops. There's Steve Ouailline's book, but that's ancient!

Last edited on
closed account (z05DSL3A)
I mean the win32 console is still showing!

Did you look at the compiler switches?
http://www.cplusplus.com/forum/windows/34280/#msg185579

I mean the win32 console is still showing!


You need to learn how to use whatever development environment you are using. All of them which I have (Dev-C++, Code::Blocks, Visual Studio 6, Visual Studio 2003, 2008) provide an initial setup screen when you create a new project where you tell the environment which type of project you want to create, i.e., Win32 Console Project, Win32 GUI Project, etc., etc. There are usually several screens where various options are set. For example, when I set up a GUI or Console project in Visual Studio I get to a screen where I check 'Empty Project', and that way Visual Studio refrains from writting wizard gobbledegook code for me. I prefer to write my own code. Anyway, after going through these screens various compiler switches will be set for when you compile your code, as intemated by Grey Wolf and others.

What you are likely doing since you no doubt learned C++ programming in a console environment is to set up your GUI project as a 'Console Project', then you no doubt inserted the Win Api code to create GUI Windows, which is just fine. If you include "Windows.h" and the lib settings are OK, everything will work and your code will create GUI Windows; but you'll still get a console screen. By the way - these can be nice for debugging.

You won't find Petzold in any bookstores. It would need to be purchased online. I provided you with links. His Windows 95 book would even be fine. It can be had for the price of postage.
I really don't mean to trouble you, but yeah I tried using code blocks using win32 GUI option, main starts with some code similar to the one posted but, when I compile, I still get the console. It's okay for now, but I am just reporting...
No trouble. Try going into Project >> Properties...

Select the 2nd tab >> 'Build Targets' Make sure for 'Type' GUI Application' is selected.

If that doesn't work something is really screwed up. Maybe we could try compiling from the command line.

We're getting pretty offtopic, all he wants to do is translate the code to WinAPI right?

Original:
1
2
3
4
5
6
7
8
9
10
11
void main()
{
	ifstream in;
	string s;
	in.open(...);
	while (getline(in, s))
	{
		cout << s << endl;
	}
                 in.close();
}


Use CreateFile & ReadFile, then use strtok to split the lines.
THANKS freddie!

Yeah that was it...
I wrote your program for you TonyAz; in fact, two versions of it. The first version uses everyone’s beloved
C++ Std. Lib. iostream/string crap. It compiles to 279,552 bytes. The 2nd version is the exact same program
done more or less my way, and compiles to 7168 bytes. The program creates a main program window with a
text box (edit control) covering the entire window. In its WM_CREATE code it reads in the source file
Main.cpp. Actually, I modified my ProgEx38 tutorial from here…

http://www.jose.it-berater.org/smfforum/index.php?topic=3389.0

to just put the edit control on the Form and read in the program’s source code file. I have several paragraphs of
discussion material commented out before the source code starts.

I’m assuming you are using CodeBlocks (you mentioned that). Create a new project of type ‘Win32 GUI
Project. Next dialog choose ‘Frame Based’. For project title type in Form1 (I guess the title doesn’t matter).
Save it to wherever you want. I usually remove the ‘Debug’ configuration’, and clear the output directory text
boxes so it puts all my files in the same directory. To run these programs paste the following code into the IDE,
which should replace what’s there. Be sure to save the main source code file as ‘Main.cpp’, as the programs
attempt to read this file into the text box from whatever directory the exe is executed from. I have to post each
program in two posts as they exceed the 8192 bytes allowed for a single post. Copy the two posts from each
program into Main.cpp however. My comments are commented out, so won’t affect compilation. Here is the
first part of the bloatware version…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*
  Form1 -- Basic Simple Template Program For Win32 Programming With The Windows Api.

  To create a GUI (Graphical User Interface) Windows program that uses the raw low
  level C Api (however, you can compile it as a C++ program) and that creates a main
  program window you must do the following things...

  1) Include the required header file support.  That would be <Windows.h>.  This is
     actually a master include that includes many other includes.  Windows is a very
     sophisticated complex system that requires many equates, structs, typedefs, and
     function prototypes.  Below you can see we've done that with the line...

     #include <Windows.h>

  2) Code a conformant Window Procedure and WinMain() function.  These procedures must
     conform to their required return values and function signatures.  In looking at
     both those procedures below you can see a lot of variable types with which you
     might not be familiar such as HWND, WPARAM, HINSTANCE.  These as well as many
     other types are defined in Windows.h or one of the headers included from Windows.h.

  3) In WinMain() declare a struct of type WNDCLASSEX (Window Class Extended) and
     fill out the members of this complex type.  Windows classifies all windows whether
     we are talking about main program windows, buttons, text boxes, ActiveX controls,
     whatever, as being members of some specific 'class'.  Its really not exactly a
     Class in the C++ sense, but rather a struct.  However, its a rather complex struct
     in that one of its members is actually a  function pointer (more about that later).
     Two particularly important WNDCLASSEX members are lpszClassName and lpfnWndProc.
     Here is the declaration of a WNDCLASSEX struct...

     typedef struct _WNDCLASSEX
     {
      UINT    cbSize;
      UINT    style;
      WNDPROC lpfnWndProc;       //Function Windows calls by sending messages
      int     cbClsExtra;
      int     cbWndExtra;
      HANDLE  hInstance;
      HICON   hIcon;
      HCURSOR hCursor;
      HBRUSH  hbrBackground;
      LPCTSTR lpszMenuName;
      LPCTSTR lpszClassName;     //name of class
      HICON   hIconSm;
     }WNDCLASSEX;


     The lpszClassName (long pointer to class name) is the name of the class.  This is a
     char string.  In the program below it is "Form1".  When it comes time to create
     an instance of the class a function named CreateWindow() will be used, and one of
     the many parameters to this function is the class name.

     The lpfnWndProc is the address of the Window Procedure that will receive messages from
     Windows when Windows itself detects that some item of interest that pertains to the
     window has occurred.  In our program below it is fnWndProc().  Windows will call
     this function (send it a message) when the window is first created, for example.  The
     message the Window Procedure will receive in that case is the WM_CREATE message.  In
     the program below our only response to that message is to put up a message box
     notifying us of the message.  There are actually hundreds of messages.  The program
     below only takes specific action on three of them.  All others are passed onto
     Default Window Proc (DefWindowProc()).  In other words, you are saying to Windows,
     "I'm not interested in that message.  You deal with it if you need to";

  4) After successfully filling out all the required member fields of the WNDCLASSEX type,
     and calling RegisterClassEx() to register the class with Windows, you then use the
     big powerful CreateWindow() or CreateWindowEx() function to create an actual instance
     of a window of the class you just registered.  The WNDCLASSEX struct specifies
     general characteristics of all windows of a class.  The CreateWindow function actually
     creates a specific window with specific dimensions, location on the screen, caption,
     Window Styles (more about that later), etc.  So in other words, or in OOP speak,
     the CreateWindow() call instantiates on object of the class specified as the 1st
     parameter of a CreateWindow() call or the 2nd parameter of a CreateWindowEx() call.
     Here is a brief description from Microsoft's documentation on the CreateWindow()
     call...

     HWND CreateWindow
     (
      LPCTSTR lpClassName,  // pointer to registered class name
      LPCTSTR lpWindowName, // pointer to window name             << window caption
      DWORD dwStyle,        // window style
      int x,                // horizontal position of window
      int y,                // vertical position of window
      int nWidth,           // window width
      int nHeight,          // window height
      HWND hWndParent,      // handle to parent or owner window
      HMENU hMenu,          // handle to menu or child-window identifier
      HANDLE hInstance,     // handle to application instance
      LPVOID lpParam        // pointer to window-creation data
     );
*/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*    
     It might be pointed out that at the point of the big CreateWindow() call down in
     WinMain(), the Window Procedure will be sent a WM_CREATE message before the
     CreateWindow() call in WinMain() returns.  Therefore, the Window Procedure will have
     first knowledge of the Window Handle Windows has assigned to the window as a result
     of the CreateWindow() call.  That hwnd will come through to the Window Procedure as
     the first parameter of the call.  In our case below a MessageBox is put up.  After
     that message has been processed by the Window Procedure and fnWndProc returns, the
     CreateWindow() call down in WinMain() will return and the hWnd will receive the handle
     to the Main Program Window.

     After that a ShowWindow() call will make the Window visible on the screen, and the
     program will enter its message loop (sometimes called the message pump) in the form
     of a while loop where it continually 'Gets' and 'Translates' messages Windows has
     placed in a message queue structure set up for that purpose.  When it receives a
     message from Windows it dispatches it to the Window Procedure for processing.  Also,
     the program's Window Procedure can be called directly from Windows bypassing the
     message queene.  In any case, the Window Procedure will receive all messages bound
     for the program in an orderly manner.

     In the program below, when you first start it, you'll get a message box telling you
     the Window Procedure has received a WM_CREATE message.  This message is only received
     one time, and in more complex programs is often used for program initialization chores
     such as creating the user interface elements, i.e., buttons, edit boxes, etc., that
     will decorate the main window.  Once the window becomes visible the only functionality
     of this program is to present message boxes when you click on the Form or [x] out to
     close the window.  However, it does have default functionality of being able to be
     resized, maximized/minimized, moved, etc.  When you do click on the little 'x' to
     close the window and program, Windows will send the Window Procedure a WM_CLOSE
     message.  I decided to handle that message by calling the DestroyWindow() Api
     function which will destroy the window and release its resources, and by calling
     PostQuitMessage() which will cause the program to exit out of the while loop message
     pump down in WinMain().

     It might be pointed out that after compiling this program with any C/C++ compiler of
     which I'm aware, your executable will be in a size range from 7 or 8 K to a max of
     perhaps 15 or 16 K, depending on the settings of various configurable compiler
     settings.  The reason its so small is that all its functionality is derived from code
     contained in core Dlls that are a part of every Windows installation.  There are no
     additional code dependencies that would increase its size as you would have for
     eample with MFC or .NET libraries.  Also, once you understand what this code is doing
     you can use it as a template or basis for creating real programs that actually do
     something useful, and you can do this without having to suffer through Wizard
     generated code and piles of extra files that are largely a mystery.
*/


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//Main.cpp
#include <windows.h>
#include <iostream>
#include <fstream>
#include <string>
#define IDC_TEXT   1500
using namespace std;

LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM 
lParam)
{
 switch(msg)
 {
  case WM_CREATE:
    {
       HWND hCtrl;
       RECT rc;
       HINSTANCE hIns=((LPCREATESTRUCT)lParam)->hInstance;
       HFONT hFont=(HFONT)GetStockObject(SYSTEM_FIXED_FONT);
       GetClientRect(hwnd,&rc);
       hCtrl=
       CreateWindow
       (
        "edit",
        "",
        WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_HSCROLL|ES_MULTILINE,
        0,
        0,
        rc.right,
        rc.bottom,
        hwnd,
        (HMENU)IDC_TEXT,
        hIns,
        0
       );
       SendMessage(hCtrl,WM_SETFONT,(WPARAM)hFont,MAKELPARAM(FALSE,0));
       ifstream in("Main.cpp");
       string s, line;
       while(getline(in,line))
             s+=line+"\r\n";
       SetWindowText(hCtrl,s.c_str());
    }
    return 0;
  case WM_CLOSE:
    {
       DestroyWindow(hwnd);
       PostQuitMessage(0);
    }
     return 0;
 }

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


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrev, LPSTR lpszArgument, int iShow)
{
 char szClassName[]="Form1";
 WNDCLASSEX wc;
 MSG messages;
 HWND hWnd;

 wc.lpszClassName=szClassName,                wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX),               wc.style=CS_DBLCLKS;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION),     wc.hInstance=hIns;
 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION),  wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW,    wc.cbWndExtra=0;
 wc.lpszMenuName=NULL,                        wc.cbClsExtra=0;
 RegisterClassEx(&wc),
 
hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,100,150,900,750,HW
ND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}


And here's the non-bloatware version. It doesn't use anything from the C++ Standard Libraries. Compile as C++ though with main source code file as Main.cpp. I'm seeing 7168 bytes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//Main.cpp
#include <windows.h>
#define IDC_TEXT 1500

LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
  case WM_CREATE:
    {
       RECT rc;
       HINSTANCE hIns=((LPCREATESTRUCT)lParam)->hInstance;
       HFONT hFont=(HFONT)GetStockObject(SYSTEM_FIXED_FONT);
       GetClientRect(hwnd,&rc);
       HWND hCtrl=
       CreateWindow
       (
        "edit",
        "",
        WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_HSCROLL|ES_MULTILINE,
        0,
        0,
        rc.right,
        rc.bottom,
        hwnd,
        (HMENU)IDC_TEXT,
        hIns,
        0
       );
       SendMessage(hCtrl,WM_SETFONT,(WPARAM)hFont,MAKELPARAM(FALSE,0));
       HANDLE hFile=CreateFile("Main.cpp",GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
       DWORD dwSize=GetFileSize(hFile,NULL);
       DWORD dwBytesRead;
       HGLOBAL pBuffer=GlobalAlloc(GPTR,dwSize+1);
       if(pBuffer)
       {
          if(hFile!=INVALID_HANDLE_VALUE)
          {
             ReadFile(hFile,pBuffer,dwSize,&dwBytesRead,NULL);
             SetWindowText(hCtrl,(char*)pBuffer);
             GlobalFree(pBuffer);
             CloseHandle(hFile);
          }
       }
    }
    return 0;
  case WM_CLOSE:
    {
       DestroyWindow(hwnd);
       PostQuitMessage(0);
    }
    return 0;
 }

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


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrev, LPSTR lpszArgument, int iShow)
{
 char szClassName[]="Form1";
 WNDCLASSEX wc;
 MSG messages;
 HWND hWnd;

 wc.lpszClassName=szClassName,                wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX),               wc.style=CS_DBLCLKS;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION),     wc.hInstance=hIns;
 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION),  wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW,    wc.cbWndExtra=0;
 wc.lpszMenuName=NULL,                        wc.cbClsExtra=0;
 RegisterClassEx(&wc),
 hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,50,150,900,750,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}
Last edited on
I probably should start a new thread on this, and since you've been so very much helpful, I would like to point out something out here:

I've noticed that the size of code/commands doesn't contribute to the size of the executable as much as the library does. For example, windows.h builds up to 714.56KB or so, with nothing else in the body. Similarly, iostream builds to 587.2KB alone, while stdio.h builds to just 18.4KB! Amazing!
I don't know if it's a compiler issue, i.e. a smart compiler that doesn't "compile" a certain function (I doubt I'm using a right term) e.g. if you're only using cout with iostream, cin and others would be ignored. I don't know if there is such a thing here.

Back to my original problem, I guess it's solved.

Thanks again freddie1 and all!
You must be looking at debug builds TonyAz. My non-bloated version above includes Windows.h and nothing else and is only 7 K. A "Hello, World!" with stdio.h is 5 K as opposed to the three hundred K you'll get with iostream - even on a release build optimized for small code size. Also check out your optimazations under 'Build Options'. With those you can affect speed and size.
Topic archived. No new replies allowed.
Pages: 12