Background image fails to get set for a window in WinApi - c

I am learning to how to set a background image for a window in C.
Here is my code:
#include <stdio.h>
#include <windows.h>
char* window_name = "Window";
char* window_title = "Window Title";
char* background_name = "test.bmp";
int window_width = 600;
int window_height = 400;
HBITMAP hbackground_image;
WNDCLASSEX wc;
HWND hwnd, hbackground;
MSG msg;
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_CREATE:
hbackground = CreateWindow("STATIC", "background", SS_BITMAP | WS_CHILD | WS_VISIBLE, 0, 0, 300, 300, hwnd,
NULL, NULL, NULL);
hbackground_image = (HBITMAP)LoadImage(NULL, background_name, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
SendMessage(hbackground, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbackground_image);
break;
default:
return DefWindowProc(hwnd, msg, wp, lp);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
wc.lpszClassName = window_name;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Windows registration failure", NULL, MB_RETRYCANCEL);
return 1;
}
hwnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, window_name, window_title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT, window_width, window_height, NULL, NULL, hInstance, NULL);
// hwnd = CreateWindow("test", "test title", WS_OVERLAPPED | WS_VISIBLE, 100, 100, 500, 500, NULL, NULL, NULL, NULL); // This fails
if (!hwnd) // If fails
{
MessageBox(NULL, "Window creation failed :(", NULL, MB_RETRYCANCEL);
return 2;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
However, the background image doesn't get set even though there is a bitmap in the same folder as the .exe. I also tried different bitmaps from the internet, and one I made in paint. Any help would be appreciated.

This line is wrong:
wc.lpfnWndProc = DefWindowProc;
You are not seeing your background image because you are not using your WindowProcedure() with the window class, and thus it is never called to load/display the bitmap.
That line needs to be this instead:
wc.lpfnWndProc = WindowProcedure;
Also, when processing WM_CREATE, you are not return'ing any value, so the result is indeterminate, which is undefined behavior. You need to return 0; for that message:
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_CREATE:
...
return 0;
...
}
return DefWindowProc(hwnd, msg, wp, lp);
}

Related

Why does BitBlt() Zoom in when copying the exact same pixels from the same bitmap onto itself?

I'm trying to make a window that copies the desktop, and mess around with the pixels on it. I do this by using BitBlt from the Desktop Handle to my Window handle. This works as expected - a window is created which looks exactly like the desktop. However, when I use BitBlt() again to move a segment of pixels from my Window to another area of my Window, the pixels are zoomed in. Why does this happen and how do I fix it?
Here is the code, I have commented on the section where the issue seems to be coming from:
#include <windows.h>
int myWidth, myHeight;
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
HDC DhWnd = GetDC(HWND_DESKTOP);
HDC MhWnd = GetDC(hwnd);
BitBlt(MhWnd, 0, 0, myWidth, myHeight, DhWnd, 0, 0, SRCCOPY);
ShowWindow(hwnd, SW_SHOW);
BitBlt(MhWnd, 300, 0, 100, 500, MhWnd, 300, 0, SRCCOPY);
/*^^^^ The above segment zooms in the pixels despite copy pasting the EXACT
SAME coordinates of the bitmap onto itself. ^^^^*/
ReleaseDC(hwnd, DhWnd);
ReleaseDC(hwnd, MhWnd);
return 0;
}
case WM_PAINT:
ValidateRect(hwnd, NULL);
return 0;
case WM_CLOSE:
case WM_DESTROY:
DestroyWindow(hwnd);
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
RECT Drc;
MSG msg;
HWND DhWnd = GetDesktopWindow();
HWND MyhWnd;
GetWindowRect(DhWnd, &Drc);
myWidth = Drc.right - Drc.left;
myHeight = Drc.bottom - Drc.top;
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyWindow";
if (!RegisterClass(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
MyhWnd = CreateWindow("MyWindow", NULL, WS_POPUP, 0, 0, myWidth, myHeight, NULL, NULL, hInstance, NULL);
if (MyhWnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}

WinAPI, TreeView: a gray item by TVIS_CUT

I want to make a item gray. According to docs I set TVIS_CUT in stateMask and mask.
But it doesn't work (the item is black as usual). TVIS_BOLD works perfect.
I use CodeBlocks17 (gcc)/Win7x64. Also I tried VS2005 and another OS (WinXP) with the same result.
What did I miss?
#define _UNICODE
#define UNICODE
#include <windows.h>
#include <commctrl.h>
LRESULT CALLBACK cbMain (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
MSG msg;
WNDCLASSEX wc{0};
wc.hInstance = hInstance;
wc.lpszClassName = TEXT("MyAppClass");
wc.lpfnWndProc = cbMain;
wc.style = CS_DBLCLKS;
wc.cbSize = sizeof (WNDCLASSEX);
wc.hIcon = LoadIcon(0, IDC_ICON);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.lpszMenuName = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wc))
return EXIT_FAILURE;
HWND hMainWnd = CreateWindowEx (0, TEXT("MyAppClass"), NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 500, 600, 160, 300, HWND_DESKTOP, NULL, hInstance, NULL);
HWND hTreeWnd = CreateWindowEx(0, WC_TREEVIEW, NULL, WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_EDITLABELS, 0, 0, 150, 200, hMainWnd, (HMENU)100, hInstance, NULL);
TVITEM tvi{0};
tvi.mask = TVIF_TEXT | TVIF_STATE;
tvi.pszText = TEXT("Item");
tvi.cchTextMax = 40;
tvi.stateMask = TVIS_CUT;
tvi.state = TVIS_CUT;
TVINSERTSTRUCT tvins{0};
tvins.item = tvi;
tvins.hInsertAfter = TVI_ROOT;
tvins.hParent = TVI_ROOT;
SendMessage(hTreeWnd, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK cbMain (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
I used Custom Draw as Jonathan Potter said.
Here is one pitfall: while a current item changing, old item has CDIS_FOCUS and CDIS_SELECTED flags in pCustomDraw->nmcd.uItemState member, and new item doesn't have. So pCustomDraw->clrText = (pNMTVCD->nmcd.uItemState & CDIS_FOCUS) == CDIS_FOCUS) ? ... will works a little bit strange. I checked pCustomDraw->clrTextBk instead. But it can be broken when user used a custom theme.
I use this article and an applied code to build the example.
#define _UNICODE
#define UNICODE
#define _WIN32_WINNT 0x0501
#define _WIN32_IE 0x0500
#include <windows.h>
#include <commctrl.h>
#define IDC_TREEVIEW 100
LRESULT CALLBACK cbMain (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
MSG msg;
WNDCLASSEX wc{0};
wc.hInstance = hInstance;
wc.lpszClassName = TEXT("MyAppClass");
wc.lpfnWndProc = cbMain;
wc.style = CS_DBLCLKS;
wc.cbSize = sizeof (WNDCLASSEX);
wc.hIcon = LoadIcon(0, IDC_ICON);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.lpszMenuName = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wc))
return EXIT_FAILURE;
HWND hMainWnd = CreateWindowEx (0, TEXT("MyAppClass"), NULL, WS_OVERLAPPED | WS_VISIBLE | WS_SYSMENU, 500, 600, 160, 300, HWND_DESKTOP, NULL, hInstance, NULL);
HWND hTreeWnd = CreateWindowEx(0, WC_TREEVIEW, NULL, WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_EDITLABELS, 0, 0, 150, 200, hMainWnd, (HMENU)IDC_TREEVIEW, hInstance, NULL);
TVITEM tvi{0};
TVINSERTSTRUCT tvins{0};
tvi.mask = TVIF_TEXT | TVIF_STATE;
tvi.pszText = TEXT("Item1");
tvi.cchTextMax = 40;
tvi.stateMask = 0;
tvi.state = 0;
tvins.item = tvi;
tvins.hInsertAfter = TVI_ROOT;
tvins.hParent = TVI_ROOT;
SendMessage(hTreeWnd, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
tvi.pszText = TEXT("Item2");
tvins.item = tvi;
SendMessage(hTreeWnd, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
tvi.stateMask = TVIS_CUT;
tvi.state = TVIS_CUT;
tvi.pszText = TEXT("Item3");
tvins.item = tvi;
SendMessage(hTreeWnd, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK cbMain (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_DESTROY: {
PostQuitMessage (0);
}
break;
case WM_NOTIFY: {
NMHDR* pHdr = (LPNMHDR)lParam;
if (pHdr->idFrom == IDC_TREEVIEW && pHdr->code == NM_CUSTOMDRAW) {
LPNMTVCUSTOMDRAW pCustomDraw = (LPNMTVCUSTOMDRAW)lParam;
if (pCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
return CDRF_NOTIFYITEMDRAW;
if (pCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
BOOL isCut = TreeView_GetItemState(pHdr->hwndFrom, (HTREEITEM)pCustomDraw->nmcd.dwItemSpec, TVIS_CUT) & TVIS_CUT;
pCustomDraw->clrText = pCustomDraw->clrTextBk != RGB( 255, 255, 255) ? RGB( 255, 255, 255) :
isCut ? RGB( 128, 128, 128 ) : RGB( 0, 0, 0);
}
return CDRF_DODEFAULT;
}
}
break;
default:
return DefWindowProc (hWnd, message, wParam, lParam);
}
return 0;
}

Win32 API Child window doesn't appear in parent's area

I am trying to write a simple app in Win32 API. The goal is to create a parent window with blue background and a child window (visible as a small red square) inside it.
I define a parent and child windows:
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GAMEPRACTICE3));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 255));
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_GAMEPRACTICE3);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassEx(&wcex);
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE | WS_BORDER,
0,0, 400, 600, HWND_DESKTOP, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Child window
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpszClassName = childClass;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hInstance = hInst;
wc.hbrBackground = CreateSolidBrush(RGB(255, 0, 0));
wc.lpfnWndProc = WndProc;
RegisterClassEx(&wc);
HWND hwnd_child = CreateWindow(childClass, NULL,
WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
0, 0, 32, 32,
hWnd, 0, hInst, 0);
ShowWindow(hwnd_child, nCmdShow);
UpdateWindow(hwnd_child);
When I launch the app I get the following output:
It seems that the child window is not displaying at all.
I tried to search similar problems on the Internet but none of the solutions worked for me so far.
Source code:
#include "stdafx.h"
#include "GamePractice3.h"
#define MAX_LOADSTRING 100
HINSTANCE hInst;
WCHAR szTitle[MAX_LOADSTRING];
WCHAR szWindowClass[MAX_LOADSTRING];
WCHAR childClass[MAX_LOADSTRING];
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_GAMEPRACTICE3, szWindowClass, MAX_LOADSTRING);
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GAMEPRACTICE3));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 255));
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_GAMEPRACTICE3);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassEx(&wcex);
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GAMEPRACTICE3));
MSG msg;
hInst = hInstance;
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE | WS_BORDER,
0,0, 400, 600, HWND_DESKTOP, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpszClassName = childClass;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hInstance = hInst;
wc.hbrBackground = CreateSolidBrush(RGB(255, 0, 0));
wc.lpfnWndProc = WndProc;
RegisterClassEx(&wc);
HWND hwnd_child = CreateWindow(childClass, NULL,
WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
0, 0, 32, 32,
hWnd, 0, hInst, 0);
ShowWindow(hwnd_child, nCmdShow);
UpdateWindow(hwnd_child);
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
Any help would be appreciated :).
For Child window doesn't appear in parent's area issue, in addition to #daniel_p's answer:
WS_OVERLAPPEDWINDOW style is not relevant here. This style gives the window a title bar, a window menu, a sizing border, and minimize and maximize buttons.
Error checking is necessary. You will find that register child window class failed and return 0.
Specify a valid null-terminated string for class name. Class name is NULL is one of factors cause RegisterClassEx fail.
Initialize WNDCLASSEX struct like: WNDCLASSEX wc = {0}; Without initialization, some value which you don't set explicitly later will be garbage value. This is another factor cause RegisterClassEx fail. Or you can set every value explicitly.
With the following editions your code will work:
WCHAR childClass[MAX_LOADSTRING] = L"Child Window";
// ...
WNDCLASSEX wc = {0};
Example for error checking of RegisterClassEx function:
DWORD errCode = 0;
ATOM childClassId = RegisterClassEx(&wc);
if (!childClassId)
{
errCode = GetLastError();
MessageBox(NULL, L"RegisterClassEx failed!", L"Error", MB_ICONERROR | MB_OKCANCEL);
return 0;
}
I managed to resolve the issue.
I removed WS_OVERLAPPEDWINDOW from the creation of the child window
I added seperate Window Procedure for the child window with
DefWindowProc
I created a string for childClass and loaded it (LoadStringW)
I initialized all 11 fields of WNDCLASSEXW structure (not sure if it's necessary)
Hope it helps.

SB_THUMBTRACK is not sent repeatedly

MSDN says the following about SB_THUMBTRACK:
The user is dragging the scroll box. This message is sent repeatedly
until the user releases the mouse button. The HIWORD indicates the
position that the scroll box has been dragged to.
However, I am only getting this message once (when I click on the scroll box).
This is my code:
#include <Windows.h>
HWND hEdit;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_HSCROLL:
if (LOWORD(wParam) == SB_THUMBTRACK)
{
// Display some text
SendMessage(hEdit, WM_CHAR, 'a', 0);
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "WinClass";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wc);
//--------------------------------------------
// Create Window
HWND hWnd = CreateWindowEx(0, "WinClass", "My Title", WS_OVERLAPPEDWINDOW, 200, 200, 500, 300, NULL, NULL, hInstance, NULL);
// Create horizontal Scrollbar
CreateWindowEx(0, "SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE| SBS_HORZ, 50, 50, 300, 20, hWnd, NULL, hInstance, NULL);
// Create Edit control
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 10, 10, 250, 21, hWnd, NULL, hInstance, NULL);
// Show Window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//--------------------------------------------
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Because you do not set the scrollbar info, the system could not calculate the track position.
After setting the scrollinfo,
#include "stdafx.h"
#include <Windows.h>
#include <string.h>
#include <stdlib.h>
#include <Commctrl.h>
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#pragma comment(lib, "Comctl32.lib")
HWND hEdit;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_HSCROLL:
if (LOWORD(wParam) == SB_THUMBTRACK)
{
int i = 0;
char buf[3];
_itoa_s(HIWORD(wParam), buf, 3, 10);
SetWindowText(hEdit, buf);
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "WinClass";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wc);
//--------------------------------------------
InitCommonControls();
// Create Window
HWND hWnd = CreateWindowEx(0, "WinClass", "My Title", WS_OVERLAPPEDWINDOW, 200, 200, 500, 300, NULL, NULL, hInstance, NULL);
// Create horizontal Scrollbar
HWND hScroll = CreateWindowEx(0, "SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ, 50, 50, 300, 20, hWnd, NULL, hInstance, NULL);
// Create Edit control
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 10, 10, 250, 21, hWnd, NULL, hInstance, NULL);
SCROLLINFO si = {0};
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
si.nMin = 0;
si.nMax = 100;
si.nPage = 10;
si.nPos = 0;
si.nTrackPos = 0;
SetScrollInfo(hScroll, SB_CTL, &si, true);
// Show Window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//--------------------------------------------
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
everything should work well.

Control Size To Fit Window Size

I have a textbox on a form and i want to set it to match the height/width of the window. Is there any way to do this in C? To be clear this is C not C-Sharp (C#). I'm using DevC++
Code i have to create TextBox:
HWND hwndText = CreateWindow(
TEXT("edit"),
TEXT(""),
WS_VISIBLE | WS_CHILD | WS_BORDER | WS_HSCROLL | WS_VSCROLL| ES_MULTILINE | ES_AUTOHSCROLL,
0,0,
630,470, //Height & Width
hwnd,
(HMENU)ID_MYTEXT,
hInstance,
NULL
);
Full Source:
#include <windows.h>
const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
HMENU ID_MYTEXT;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Title",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, hInstance, NULL
);
HWND hwndText = CreateWindow(
TEXT("edit"),
TEXT(""),
WS_VISIBLE | WS_CHILD | WS_BORDER | WS_HSCROLL | WS_VSCROLL| ES_MULTILINE | ES_AUTOHSCROLL,
0,0,
630,470,
hwnd,
(HMENU)ID_MYTEXT,
hInstance,
NULL
);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
SendMessage(hwndText, WM_SETTEXT, 0, (LPARAM)"");
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
If this is all you want to have in your window, then why not remove the WS_CHILD style and make the button the whole window?
The other alternative is to handle WM_SIZE message and resize your child button window there.
The shortest version of first example looks like this:
#include "stdafx.h"
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hWnd = CreateWindow(_T("BUTTON"), L"testButton", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}

Resources