Hello Windows Programmers!
I am new to windows programming using winapi. I was reading this very nice book and I encountered a problem(displayed as a black box) when I display unicode character U+5167 (內) in the client area using DrawText and TextOut. Mysteriously, this particular unicode character is properly displayed in windows caption area. This unicode character is also displaying correctly when I display it using the MessageBox. Finally, I tried displaying other unicode characters that are relatively near to this unicode like U+5166, U+5168, U+5157 and U+5177;
Here's a link for this unicode character as defined by the standards.
http://unicode-table.com/en/#5167
Note : I am compiling this code using Unicode using Visual Studio 2010
Below is my code.
#include<windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("HelloWin");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if(!RegisterClass (&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName,
TEXT("內Sample text 內篇 日本国 渡瀬 內篇全兦兗具 кошка"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
LPTSTR c = TEXT("內Sample text 內篇 日本国 渡瀬 內篇全兦兗具 кошка");
switch(message)
{
case WM_CREATE:
PlaySound(TEXT("shutda.wav"), NULL, SND_FILENAME | SND_ASYNC);
MessageBox(hwnd, c, c, 0);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawTextEx(hdc, c, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER, NULL);
TextOut(hdc, 100, 100, TEXT("內篇 日本国 кошка unicode"), 19);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
For non windows programmers, you can compile and run this code by copy and pasting this directly to a .cpp file. If you are using VS2010, you just need to create new "Win32 Application" project and select "Empty Project". After that, you need to add a cpp file for example "test.cpp" in the source folder of your project. Then copy and past the code
to the "test.cpp" then build and run it. You should now see my problem. :)
When a valid character is displayed as a rectangular box, that indicates that the font does not contain a glyph for the characters. In order to solve the problem you need to use a font which does have a glyph for this character.
Related
I found that on windows 11, even if I created windows with WS_EX_TOPMOST style, the window still get covered by taskbar if you click anywhere on the taskbar. The only exception to this is task manager. How does it achieve it?
I want a feature to draw stuff on the taskbar, or at least mimic that behavior using a transparent window. I think there used to be 2 ways to achieve that:
Get DC of taskbar and draw (which no longer work on Windows11)
Create a transparent window and keep it on top of taskbar (issues with how to keep it topmost)
I kind of get stuck now. Any help is appreciated.
UPDATE:
I just noticed that the taskbar window, shown as DesktopWindowXamlSource in Spy++ does not have the WS_EX_TOPMOST style set. I guess it's possible to cover it for some ways?
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <iostream>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
WS_EX_TOPMOST, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// All painting occurs here, between BeginPaint and EndPaint.
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
And this is how the window get covered by taskbar when I click start.
I am learning window API programming.
However I am getting stuck in loading image and showing on the window.
#include <windows.h>
#include <stdio.h>
#define wname "mywin"
LRESULT CALLBACK WndProc(HWND h,UINT im,WPARAM wp,LPARAM lp);
int APIENTRY WinMain(HINSTANCE his, HINSTANCE prev,LPSTR cmd, int cshow)
{
WNDCLASS wc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.lpszMenuName=NULL;
wc.style=CS_HREDRAW | CS_VREDRAW;
wc.hInstance = his;
wc.lpszClassName = wname;
wc.lpfnWndProc = (WNDPROC)WndProc;
RegisterClass(&wc);
HWND h = CreateWindow(wname, wname, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, (HMENU) NULL, his, NULL );
ShowWindow(h, cshow);
MSG Message;
while(GetMessage(&Message,0,0,0))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}
LRESULT CALLBACK WndProc(HWND h, UINT im, WPARAM wp, LPARAM lp)
{
HBITMAP static hbm;
HDC static mdc;
BITMAP static bm;
switch(im)
{
case WM_CREATE:
{
hbm = (HBITMAP) LoadImage(NULL, "../img/1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(hbm, sizeof(bm), &bm);
if(!hbm)
{
MessageBox(h, "Error loading bitmap", "msg", MB_OK);
}
break;
}
case WM_PAINT:
{
HDC hdc = GetDC(h);
mdc = CreateCompatibleDC(hdc);
SelectObject(mdc, hbm);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, mdc, 0, 0, SRCCOPY);
break;
}
}
I tried this code.
There is no grammer error, but the output is wierd.
Picture appears, but without window, and the program stopped.
I think the probelm is on WM_CREATE part in 'LRESULT CALLBACK WndProc' , but cannot figure out exactly what is wrong. HELP!!!
(WinMain is ok, here is no problem)
It seems you have no return value for WndProc and probably Win32 messages are not processed by default.
(after case WM_PAINT):
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
This code no longer works on Windows 7 or 8.
Aren't SysAnimate32 controls supported on them ?
Is there a way to make it work as it used to work on Windows XP ?
(I am required to write more details but I have no more details to talk about :)
thanks
#include <windows.h>
#include <CommCtrl.h>
HINSTANCE hInstance;
#define IDC_MYANIMATE 9
HWND CreateAnimationControl (HWND hParent)
{
HWND hAnimation = Animate_Create( hParent, IDC_MYANIMATE, ACS_AUTOPLAY | WS_BORDER | WS_CHILD, hInstance);
Animate_Open (hAnimation, "test.avi");
ShowWindow (hAnimation, SW_SHOW);
return hAnimation;
}
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hAnimation = NULL;
switch (uiMsg)
{
case WM_DESTROY:
PostQuitMessage (0);
break;
case WM_CREATE:
hAnimation = CreateAnimationControl (hWnd);
break;
case WM_SHOWWINDOW:
if (wParam)
{
MoveWindow (hAnimation, 0, 0, 300, 300, TRUE);
Animate_Play (hAnimation, 0, -1, -1);
}
break;
}
return DefWindowProc (hWnd, uiMsg, wParam, lParam);
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpsCmdLine, int iCmdShow)
{
WNDCLASSEX WindowClass;
HWND hWnd;
MSG uMsg;
hInstance = GetModuleHandle (NULL);
WindowClass.cbClsExtra = 0;
WindowClass.cbSize = sizeof (WNDCLASSEX);
WindowClass.cbWndExtra = 0;
WindowClass.hbrBackground = CreateSolidBrush (RGB (0, 0, 0));
WindowClass.hCursor = LoadCursor (NULL, IDC_ARROW);
WindowClass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
WindowClass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
WindowClass.hInstance = hInstance;
WindowClass.lpfnWndProc = WindowProcedure;
WindowClass.lpszClassName = "1";
WindowClass.lpszMenuName = NULL;
WindowClass.style = 0;
if (!RegisterClassEx (&WindowClass))
{
MessageBox (NULL, "Window class registration has failed!", "Error:", MB_OK | MB_ICONERROR);
return 0;
}
hWnd = CreateWindow ("1", "Win32 Animation Testing", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
hInstance, NULL);
if( ! hWnd )
{
MessageBox (NULL, "Window creation has failed!", "Error:", MB_OK | MB_ICONERROR);
return 0;
}
ShowWindow( hWnd, SW_SHOW );
UpdateWindow( hWnd );
while( GetMessage( &uMsg, NULL, 0, 0 ) > 0 )
{
TranslateMessage( &uMsg );
DispatchMessage ( &uMsg );
}
return ( int ) uMsg.wParam;
}
No, that still works just fine when I tried your code on Windows 8, compiled with VS2012. A screenshot to prove it:
Notable is that your error checking is lacking, you don't pay attention to the return value of Animate_Open(). A FALSE return indicates that it could not open the .avi file. Many possible reasons, there's no better diagnostic from that function than "could not do it".
It was difficult to find a .avi file that it could handle, the control is stone-cold old and cannot handle but the simplest ones. In particular an .avi file that also has a audio track will not open, as documented by the MSDN Library. The test one I used was a very simple one I dug out of the Visual Studio image library, Animations/filecopy_16.avi.
So basic checks, after adding the error handling, is to ensure that the file is actually present in the same directory as your EXE and that it is a very simple .avi file that at least plays back in WMP.
I am new to Windows Programming.
I created a win32 console project (without preCompiled header) with VS2005. And the code as below.
// HelloWin.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include "stdafx.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int _tmain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("HelloWin");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This Program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, // window class name
TEXT("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(message)
{
case WM_CREATE:
PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("Hello Windows XP"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
And now there is two Link Errors as this, Could anybody help me to fix this errors.
Does it caused by there is no hellowin.wav file in my local harddisk? If it does. What directory can I place a simular WAV file to?
Thanks.
1>Linking... 1>HelloWin.obj :
error LNK2019: unresolved external
symbol imp__PlaySoundW#12 referenced in function "long __stdcall
WndProc(struct HWND *,unsigned int,unsigned int,long)"
(?WndProc##YGJPAUHWND__##IIJ#Z)
1>D:\learning\windows\ProgrammingWindows(5thEdition)\HelloWin\Debug\HelloWin.exe
:
fatal error LNK1120: 1 unresolved externals 1>Build log was saved at
"file://d:\learning\windows\ProgrammingWindows(5thEdition)\HelloWin\HelloWin\Debug\BuildLog> .htm"
1>HelloWin - 2 error(s), 1 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
You have several problems here. Firstly you say that your application is a console app. If it is, then you are using the wrong main. Your subsystem is probably WINDOWS in which case your main should be this instead:
int CALLBACK _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow)
You also say you're not using precompiled headers but you have an include for stdafx.h. Your problems can be fixed by changing your main and also changing your includes to look like this:
#include <windows.h>
#include <tchar.h>
#pragma comment(lib, "Winmm.lib")
This allows the linker to look for the library file we tell it to. I also got rid of your precompiled header and replaced it with tchar.h since that is your only other dependency so far.
The fact hellowin.wav is not present at compilation time is irrelevant. The program only looks for it at runtime.
I have a window with an edit control as its child. The control is in focus. Every time I switch to some other application the control loses the focus (blurs). Do I have to keep track of the focused control in order to manually focus back when returning to the app back again? Or am I doing something wrong? I would expect Windows keeps track of such things automatically but who knows?
I'm on Win32 using plain C. Example:
#include <windows.h>
#define NAME "test"
LRESULT CALLBACK WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND edit1, edit2;
switch (msg)
{
case WM_CREATE:
edit1 = CreateWindow("edit", "", WS_CHILD|WS_VISIBLE, 0, 0, 200, 50, hWnd, NULL, NULL, NULL);
edit2 = CreateWindow("edit", "", WS_CHILD|WS_VISIBLE, 250, 0, 200, 50, hWnd, NULL, NULL, NULL);
return 0;
case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = WinProc;
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 = NAME;
wc.lpszClassName = NAME;
RegisterClass(&wc);
HWND win;
win = CreateWindow(NAME, "test", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, NULL, NULL, hInstance, NULL);
ShowWindow(win, nCmdShow);
UpdateWindow(win);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
When another application is made active, your window receives the WM_ACTIVATE notification (wParam set to WA_INACTIVE).
When your application is made active again, your window will receive the WM_ACTIVATE notification again, this time with wParam set to WA_ACTIVE or WA_CLICKACTIVE
Since you're not using the dialog manager, you may need to set focus to the edit control yourself when you're activated.
If in doubt, use Spy++ on a dialog window, and watch the message traffic when the app is deactivated and then activated again.*