Creating a toolbar with icons

Hi, first post.

I'm using Visual Studio for my IDE. I want to create a toolbar with clickable icons to select different tools [similar to Microsoft Paint].

I'm struggling to find any resources online about how to do this. It seems to be more of a graphics programming problem? So I've looked at using SDL2, but I don't really know where to begin.

I did find some code that I modified slightly which allows one to write bitmap files to disk, but I can't get it to draw a toolbar and appropriate images.

Any references or guidance really appreciated.
How to Create Toolbars - Windows applications | Microsoft Docs
https://docs.microsoft.com/en-us/windows/win32/controls/create-toolbars

A bit of 'net searching finds quite a number of resources for creating toolbars in Windows apps.
https://duckduckgo.com/?q=win32+api+toolbar&t=ffsb&ia=web
If you are new to Windows programming then you'll have a hard time to implement this, I recommend you to start from more simple task.

Just to learn how to load a bitmap from memory takes a lot of work if you never done it and it's completely unrelated to to basic creation of toolbar.

Here is example code how to load resource from memory, although you'll need to adjust the code a litle:
https://docs.microsoft.com/en-us/windows/win32/menurc/using-resources

If you wan't working solution for resource load, let me know I'll give you my function but it wont help you much because what you are asking for isn't simple task.
Thanks both. I haven't done Windows programming before I guess if possible I'd like it to be as portable as possible but am happy to begin with windows programming as a start. I learnt to read a bitmap file / write a file to disk but that's all.

Malibor what task would recommend beginning with instead?
If you have never done Windows GUI programming then start with the basics. A list of tutorials:

https://duckduckgo.com/?q=win32+api+tutorial&t=ffsb&ia=web

Programming Win32 GUI is much more complicated than for console mode. A simple console mode program:

1
2
3
4
5
6
#include <iostream>

int main()
{
   std::cout << "Hello World!\n";
}


The simplest Windows-based program that comes closest to being as easy as console mode:

1
2
3
4
5
6
7
8
#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
{
   MessageBox(NULL, TEXT("Hello World!"), TEXT("Hello Message"), MB_OK);

   return 0;
}


The Win32 API is C-based, though a properly written program can be compiled as C++.

Now a minimal Windows GUI program (with lots of comments):

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// INCLUDES ====================================================================
#include <windows.h>

// FUNCTION PROTOTYPES =========================================================
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


// entry point for a Windows application =======================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nWinMode)
{
   // define the window class name
   static const TCHAR szAppName[]  = TEXT("1-3_MinimalWindowsApp");

   // create an instance of the window class structure
   WNDCLASSEX wc;

   // fill the structure
   wc.cbSize        = sizeof(WNDCLASSEX);
   wc.style         = CS_HREDRAW | CS_VREDRAW;
   wc.lpfnWndProc   = WndProc;
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = 0;
   wc.hInstance     = hInstance;
   wc.hIcon         = (HICON)   LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
   wc.hIconSm       = (HICON)   LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
   wc.hCursor       = (HCURSOR) LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
   wc.hbrBackground = (HBRUSH)  (COLOR_WINDOW + 1);
   wc.lpszMenuName  = NULL;
   wc.lpszClassName = szAppName;

   // register the window class (tell Windows the particulars of your app)
   if (0 == RegisterClassEx(&wc))
   {
      MessageBox(NULL, TEXT("Can't Register the Window Class!"), szAppName, MB_OK | MB_ICONERROR);
      return E_FAIL;
   }

   // define the application title
   static const TCHAR szAppTitle[] = TEXT("Win32 API Skeletal Application");

   // create the window
   HWND hwnd = CreateWindow(szAppName, szAppTitle,
                            WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            NULL, NULL, hInstance, NULL);

   // check if the window was created, exit if fail
   if (NULL == hwnd)
   {
      MessageBox(NULL, TEXT("Unable to Create the Main Window!"), szAppName, MB_OK | MB_ICONERROR);
      return E_FAIL;
   }

   // show and update the window
   ShowWindow(hwnd, nWinMode);
   UpdateWindow(hwnd);

   static BOOL bRet;
   static MSG  msg;

   // enter the main message loop
   while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) // 0 = WM_QUIT
   {
      // check for error
      if (-1 == bRet)
      {
         // handle the error and possibly exit

         // for this app simply report error and exit
         MessageBox(NULL, TEXT("Unable to Continue!"), szAppName, MB_OK | MB_ICONERROR);
         return E_FAIL;
      }
      else
      {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
      }
   }

   // the app is done, exit normally, return control to Windows
   return (int) msg.wParam;
}


// processes the messages that Windows sends to the application ================
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   // choose which Windows messages you want to use
   switch(message)
   {
   case WM_PAINT:
      HDC         hdc;
      PAINTSTRUCT ps;
      hdc = BeginPaint(hwnd, &ps);

      // draw some text centered in the client area
      RECT rect;
      GetClientRect(hwnd, &rect);
      DrawText(hdc, TEXT("Hello, Windows!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

      EndPaint(hwnd, &ps);
      return S_OK;

   case WM_DESTROY:
      // exit the application
      PostQuitMessage(0);
      return S_OK;
   }

   // let Windows process any unhandled messages
   return DefWindowProc(hwnd, message, wParam, lParam);
}

A console mode program stops and waits for user interaction, a Win32 program waits for Windows informs it there is something it needs to do. Completely different programming model.

MFC is a C++ based framework for creating Windows apps:

MinimalMFCApp.hpp:
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
#pragma once

// compile for Windows 7 or higher
#define WINVER       0x0601
#define _WIN32_WINNT 0x0601

// compiling for Windows 10 (recommended)
//#define WINVER       0x0A00
//#define _WIN32_WINNT 0x0A00

#include <afxwin.h>

// application class
class CTheApp : public CWinApp
{
public:
   BOOL InitInstance();
};

// main window class
class CMainWnd : public CFrameWnd
{
public:
   CMainWnd();

protected:
   afx_msg void OnPaint();

   DECLARE_MESSAGE_MAP()
};

MinimalMFCApp.cpp:
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
#include "MinimalMFCApp.hpp"

// construct a window
CMainWnd::CMainWnd()
{
   Create(NULL, __T("An MFC Application Skeleton"));
}


// initalize the application
BOOL CTheApp::InitInstance()
{
   m_pMainWnd  = new CMainWnd;

   m_pMainWnd->ShowWindow(m_nCmdShow);
   m_pMainWnd->UpdateWindow();

   return TRUE;
}


// application's message map
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
   ON_WM_PAINT()
END_MESSAGE_MAP()


// draw some text centered in the client area
void CMainWnd::OnPaint()
{
   CRect    rect;

   GetClientRect(&rect);

   CPaintDC dc(this);

   dc.DrawText(_T("Hello, MFC!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}

If you don't understand the Win32 API or MFC code, don't sweat it. The Windows GUI model requires a lot of "behind-the-scenes" work to make the apps work.

It takes time and a lot of skull sweat to learn GUI frameworks. Win32 or 3rd party.
Well windows programming that is (Using Windows API) isn't portable, if you want your project to run on multiple platforms such as Linux/Windows/Mac etc. then you'll need to write platform specific code for each platform and combine it into a single project. for example you would use preprocessor to conditionally compile for different platforms.

That is why some people find more easy to use cross platform GUI frameworks. but problem with such frameworks that they have limitations on what you can do with them and most often you wont be able to use standard library with them. at least not without bunch of conversion between types.

I recommend you to stick with Window API and target just Windows for now, then sometime in the future you can learn how to program for other systems.

OK, here is a beginner introduction with step by step code how to create a Window, use COM and paint it with DirectX API, it will also show you how to create a window class, so you can make use of object oriented approach:
https://docs.microsoft.com/en-us/windows/win32/learnwin32/introduction-to-windows-programming-in-c--?redirectedfrom=MSDN

Once you finish that you can learn how to create MDI window:
https://docs.microsoft.com/en-us/windows/win32/winmsg/multiple-document-interface

While the MDI link above doesn't have much code samples, you definitely need to google out for a book "Windows programing" made by Charles petzhold.
that book while old and mostly outdated is still very good reference for sample step by step code.

And in general, when ever you stuck just google "your problem" + MSDN: msdn reference is all you really need to code.

This is enough to get you started with GUI, here are more resources for specific tasks:

Direct2D:
https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-portal

Audio API:
https://docs.microsoft.com/en-us/windows/win32/medfound/microsoft-media-foundation-sdk

Cryptography:
https://docs.microsoft.com/en-us/windows/win32/seccng/cng-portal

Networking:
https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-start-page-2

Imaging:
https://docs.microsoft.com/en-us/windows/win32/api/wincodec/nf-wincodec-iwicimagingfactory-createdecoderfromfilename

Last edited on
Brilliant! Thanks both!
If you do get a copy of Petzold's Programming Windows Fifth Edition (highly recommended) there is an ongoing effort to modernize the code.

https://github.com/recombinant/petzold-pw5e

His 6th edition book is a waste of money IMO.
Topic archived. No new replies allowed.