Related
I am using WinAPI and im trying to make a program which allows you to change the title.
#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#include <tchar.h>
#include <windows.h>
#include <string>
#include <sstream>
using namespace std;
string HWNDToString(HWND inputA);
void setTitle(string inputA);
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
HWND hwnd;
MSG messages;
WNDCLASSEX wincl;
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(255,128,0));
if (!RegisterClassEx (&wincl)) return 0;
hwnd = CreateWindowEx
(
0,
szClassName,
_T("Title Changer"),
WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU,
CW_USEDEFAULT,
CW_USEDEFAULT,
400 + 22,
400 + 49,
HWND_DESKTOP,
NULL,
hThisInstance,
NULL
);
ShowWindow (hwnd, nCmdShow);
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
HWND textout, titlebutton , powerbutton, textin;
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
textout = CreateWindow("STATIC", "Enter new window title here:", WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 0, 230, 20, hwnd, NULL, NULL, NULL);
textin = CreateWindow("EDIT", "New Title", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 0, 20, 250, 25, hwnd, (HMENU) NULL, NULL, NULL);
titlebutton = CreateWindow("BUTTON", "Set as New Window Title", WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 45, 210, 25, hwnd, (HMENU) /*=*/1/*=*/, NULL, NULL);
powerbutton = CreateWindow("BUTTON", "Power Off", WS_VISIBLE | WS_CHILD | WS_BORDER, 316, 0, 100, 25, hwnd, (HMENU) 2, NULL, NULL);
break;
case WM_COMMAND:
if (LOWORD(wParam) == 1)
{
SetWindowText(hwnd, HWNDToString(textin).c_str());
MessageBox(hwnd, string("Title changed to: " + HWNDToString(textin)).c_str(), "Title Changed", MB_OK | MB_ICONINFORMATION);
}
if (LOWORD(wParam) == 2)
{
PostQuitMessage(0);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
break;
}
return 0;
}
string HWNDToString(HWND inputA)
{
stringstream stringstreamBuffer;
stringstreamBuffer << inputA;
return stringstreamBuffer.str();
}
But the program sets the title to a random hex-like string (for example, 0x123abc).
What is wrong with the HWNDToString function I defined? Do I need to use sprintf to convert hex to string?
OS: Windows 7 Ultimate x64
IDE: Codeblocks
Compiler: GNU GCC Compiler (MinGW32)
An HWND is a pointer (struct HWND__* or void*, depending on whether STRICT is enabled or disabled, respectively). Passing such a pointer to operator<< of an std::ostream-based class will invoke operator<<(const void*) which formats the pointed-to memory address as a hex string.
Since you are trying to accept a string value from the user using an EDIT control and then set your main window's title with the value of that string, you should be using the GetWindowTextLength() and GetWindowText() functions instead:
string HWNDToString(HWND inputA)
{
string s;
int len = GetWindowTextLength(inputA);
if (len > 0)
{
s.resize(len + 1);
len = GetWindowText(inputA, &s[0], s.size());
s.resize(len);
}
return s;
}
case WM_COMMAND:
if (LOWORD(wParam) == 1)
{
string s = HWNDToString(textin);
SetWindowText(hwnd, s.c_str());
MessageBox(hwnd, string("Title changed to: " + s).c_str(), "Title Changed", MB_OK | MB_ICONINFORMATION);
}
...
On a side note, your "Power Off" button should be sending a WM_CLOSE message to your main window, not calling PostQuitMessage() directly:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
...
case WM_COMMAND:
....
if (LOWORD(wParam) == 2)
{
SendMessage(hwnd, WM_CLOSE, 0, 0);
}
break;
// By default, DefWindowProc() handles WM_CLOSE by destroying the window
// using DestroyWindow(). WM_CLOSE is also received when the user closes
// the window manually. This allows you to close down your app correctly
// regardless of how the window is closed. You can handle WM_CLOSE
// manually if you want to prompt the user before allowing the
// window to be destroyed...
/*
case WM_CLOSE:
if (MessageBox(hwnd, "Are you sure you want to power down?", "Power Down?", MB_YESNO) == IDYES)
DestroyWindow(hwnd);
break;
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
See MSDN's documentation on Destroying a Window for more details.
For those who stumble upon this question, here is a very simple function to do that:
#include <string>
#include <windows.h>
string HWNDToString(HWND input)
{
string output = "";
size_t sizeTBuffer = GetWindowTextLength(input) + 1;
if(sizeTBuffer > 0)
{
output.resize(sizeTBuffer);
sizeTBuffer = GetWindowText(input, &output[0], sizeTBuffer);
output.resize(sizeTBuffer);
}
return output;
}
I want to handle a c++ win32 API button press in a native window, I'm currently attempting doing it like so -
#include <stdint.h>
#include <Windows.h>
#include <process.h>
#include <iostream>
#include <sstream>
#include <tchar.h>
#include <strsafe.h>
#include <crtdefs.h>
#include <stdafx.h>
#include <stdio.h>
#include "stdafx.h"
#include "name.h"
#include "libobs/obs.h"
#include "libobs/obs-module.h"
#define uploadName "Upload Window"
#define uploadWNDWidth 500
#define uploadWNDHeight 500
#define IDC_SELECT_VIDEO (100)
HWND hBtnParent = HWND("UploadVideo");
HWND SelectVideoBTN, UploadBTN, hWnd, hBtn;
WPARAM wmId, wmEvent;
HINSTANCE hUpload;
WNDCLASSEX wcexUpload;
int nCmdShowUpload = 1;
using namespace std;
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
//load obs modules
class load{
public:
void static loading(){
obs_module_load;
obs_module_load_locale;
}
};
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case BM_CLICK:
if (wParam == IDC_SELECT_VIDEO) {
MessageBox(hWnd, L"if", L"if", 0);
}
else{
MessageBox(hWnd, L"else", L"else", 0);
}
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
bool obs_module_load(void)
{
//init handler
//HANDLE messageLoopThreadHandler;
//set the handler to the thread
//messageLoopThreadHandler = (HANDLE)_beginthreadex(0, 0, &messageLoopThread, 0, 0, 0);
//wait for object to be in specified state
//WaitForSingleObject(messageLoopThreadHandler, INFINITE);
//startMessageThreadLoop ThreadLoopInstance;
//ThreadLoopInstance.startMyThread();
MessageBox(hWnd, L"ThreadStart", L"ThreadStart", 0);
//create message loop for buttons
//cleanup thread created by _beginThreadEx
//CloseHandle(messageLoopThreadHandler);
WNDCLASSEX vidUploader;
vidUploader.cbSize = sizeof(WNDCLASSEX);
vidUploader.style = CS_HREDRAW | CS_VREDRAW;
vidUploader.lpfnWndProc = WndProc;
vidUploader.cbClsExtra = 0;
vidUploader.cbWndExtra = 0;
vidUploader.hInstance = hUpload;
vidUploader.hIcon = LoadIcon(hUpload, MAKEINTRESOURCE(IDI_P2GOVIDEOUPLOADER20));
vidUploader.hCursor = LoadCursor(NULL, IDC_ARROW);
vidUploader.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
vidUploader.lpszMenuName = MAKEINTRESOURCE(IDC_P2GOVIDEOUPLOADER20);
vidUploader.lpszClassName = (LPCWSTR)(L"UploadVideo");
vidUploader.hIconSm = LoadIcon(wcexUpload.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassEx(&vidUploader);
hInst = hUpload; // Store instance handle in our global variable
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application dows not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
hWnd = CreateWindow((LPCWSTR)(L"UploadVideo"), (LPCWSTR)(L"Upload Video's"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hUpload, NULL);
SelectVideoBTN = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
L"Select Video's", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
10, // x position
460, // y position
100, // Button width
25, // Button height
hWnd, // Parent window
(HMENU)IDC_SELECT_VIDEO, // Assign appropriate control ID
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
UploadBTN = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
L"Upload", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
390, // x position
460, // y position
100, // Button width
25, // Button height
hWnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
RECT rect = { 0, 0, uploadWNDWidth, uploadWNDHeight };
AdjustWindowRect(&rect, GetWindowLong(hWnd, GWL_STYLE), FALSE);
SetWindowPos(hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE);
if (!hWnd)
{
MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Win32 Guided Tour"), NULL);
return 1;
}
MSG msge = { 0 };
while (PeekMessage(&msge, NULL, 0, 0, PM_REMOVE) > 0)
{
//translate and send messages
TranslateMessage(&msge);
DispatchMessage(&msge);
}
MSG msg;
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
//nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd, nCmdShowUpload);
UpdateWindow(hWnd);
load::loading();
return true;
}
When I currently load OBS, after having included the dll what happens is -
OBS starts
Window pops u
I click on window
Nothing happens
where on step 4, right after clicking on the button a MessageBox should popup saying - MessageBox(hWnd, L"else", L"else", 0); if it goes into the else, and if the if statement is true then MessageBox(hWnd, L"if", L"if", 0);
However my code won't even enter the callback function.
edit -
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
load::loading();
// Parse the menu selections:
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:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
This is where the WndProc references refer to.
You're handling the receive of the button click incorrect. You should handle a WM_COMMAND message and check the high word of the WPARAM for the notification code.
You should use GetMessage, it won't hang the program.
You can use PeekMessage if you want constant update. For example in a game where you need to constantly paint the window. It has to be something like this:
//create window...
//show window...
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
//default message processing
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//constantly paint the window when there is no other message
render_window(hwnd);
}
}
//do cleanup here
return 0;
Note that the program terminates when the above while loop is finished. You cannot put ShowWindow/UpdateWindow after that.
Second, your main window seems to be vidUploader. And the window procedure for it is set to vidUploader.lpfnWndProc = WndProc; But you have not defined WndProc. Instead you have something else called WindowProcedure
To check for button notification:
case WM_COMMAND:
if (LOWORD(wParam) == IDC_SELECT_VIDEO)
MessageBox...;
break;
I wrote a simple program; it's made of a main window and TextBox window above it. TextBox is 50% transparent. When TextBox gets a message, it draws a blue line on the main window.
The problem is that "transparent" actually is not transparent at all. If the blue line crosses a text in TextBox, the text just erased, despite the fact that the text is above. And vice versa: if I start typing, a part of the line in a row of a text just disappears instead of shine through.
Is this a bug? Or am I missing something?
#include <windows.h>
#include <stdio.h>
#define IDC_MAIN_EDIT 101
void DrawInWindow(HWND hWndToPaint){
HDC hdc = GetDC(hWndToPaint);
if(!hdc)printf("Invalid handle\n");
HPEN hPen = CreatePen(PS_SOLID,5,RGB(0, 0, 255));
SelectObject(hdc, hPen);
static float x=620, y=1, tg=0.5, ctg=2;
static int Xone = 1, Yone = 1;//depending on later recalculation this may become negative
MoveToEx(hdc,(int)x,(int)y,NULL);
if(tg<1){
y+=tg;
x+=Xone;
}else{
y+=Yone;
x+=ctg;
}
if(!LineTo(hdc, (int)x, (int)y) )printf("There are paint problem\n");
ReleaseDC(hWndToPaint,hdc);
//Now recalculate direction
RECT WndRect;
GetClientRect(hWndToPaint,&WndRect);
if(x>=WndRect.right){
if(ctg>0)ctg*=-1;//make negative
Xone=-1;
}
if(x<=WndRect.left){
if(ctg<0)ctg*=-1;//make positive
Xone=1;
}
if(y>=WndRect.bottom){
if(tg>0)tg*=-1;//make negative
Yone=-1;
}
if(y<=WndRect.top){
if(tg<0)tg*=-1;//make positive
Yone=1;
}
}
int CALLBACK EnumWindowsFunc(HWND hWnd, LPARAM lParam){
DrawInWindow(hWnd);
return false;
}
void PaintInMainWnd(){
EnumWindows(EnumWindowsFunc,0L);//Getting the handle of main window to draw
}
LRESULT __stdcall MyMainCallBckProcedure( HWND window, unsigned msg, WPARAM wp, LPARAM lp ){
switch(msg){
case WM_KEYDOWN:
if(wp == VK_ESCAPE)PostQuitMessage(0);
break;
case WM_DESTROY:
printf("\ndestroying window\n");
PostQuitMessage(0);
return 0;
case WM_SIZE:{
HWND hEdit;
RECT rcClient;
GetClientRect(window, &rcClient);
hEdit = GetDlgItem(window, IDC_MAIN_EDIT);
SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
break;
}
default:
return DefWindowProc( window, msg, wp, lp ) ;
}
}
WNDPROC lpEditWndProc;
LRESULT CALLBACK MyEditCallBckProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
if( (uMsg == WM_CHAR) && (wParam == VK_ESCAPE) )
{
PostQuitMessage(0);
return 0;
}
PaintInMainWnd();
lpEditWndProc(hWnd, uMsg, wParam, lParam);
}
bool CreateWindows(){
const char* const myclass = "myclass";
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, MyMainCallBckProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW+1),
0, myclass, LoadIcon(0,IDI_APPLICATION) };
if(RegisterClassEx(&wndclass)<0){
printf("ERR: in registering window class\n");
return false;
}
//Creating window
HWND window = CreateWindowEx( 0, myclass, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
640, 480, 0, 0, GetModuleHandle(0), 0 );
if(!window){
printf("ERR: in creating window\n");
return false;
}
ShowWindow( window, SW_SHOWDEFAULT );
//creating TextBox on the window
HFONT hfDefault;
HWND hEdit;
hEdit = CreateWindowEx(0, "edit", "",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
window, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
if(hEdit == NULL){
MessageBox(window, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
return false;
}
hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
//Now resize TextBox to fill whole parent window
RECT RectSize;
GetClientRect(window,&RectSize);
hEdit = GetDlgItem(window,IDC_MAIN_EDIT);
SetWindowPos(hEdit, 0,0,0,RectSize.right,RectSize.bottom,SWP_NOZORDER);
//Let's try to catch some messages in TextBox...
lpEditWndProc = (WNDPROC)SetWindowLongPtr(hEdit, GWL_WNDPROC, (LONG_PTR)&MyEditCallBckProcedure);
//Making hEdit transparent
SetWindowLongPtr(hEdit,GWL_EXSTYLE, WS_EX_LAYERED | GetWindowLongPtr(hEdit, GWL_EXSTYLE) );
SetLayeredWindowAttributes(hEdit, 0, (255*50)/100, LWA_ALPHA);
return true;
//###
}
int main(){
if(!CreateWindows() ){printf("Something gone wrong\n");return 1;}
MSG msg;
while(GetMessage(&msg,0,0,0) ){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Don't know is it important, but I should also mention, that I have tested only under Ubuntu with Wine, as my Windows is screwed up by this bug. Anyway, I hope the problem is not in Wine itself.
And sorry for amount of code, I really don't know what to remove to make it smaller.
I found the workaround. I created background top level window, and made foreground window 50% trasparent. I draw the lines in background window. If the front window moved or resized, the back window reacts accordingly with help of WM_WINDOWPOSCHANGED message, it sent on every little move/resize.
Anyway, this workaround is little dirty because of:
Linux/wine specific problems: 1) Display Manager do not decorate transparent window of wine(but this could be evaded by making second window 0% transparent) 2) Dragged window wobbling, but the second moving straight. All OS specific problem: second window is visible in the taskbar. Theoretically the last could be avoided by adding WS_EX_TOOLWINDOW to unowned window. The quote
To prevent the window button from being placed on the taskbar, create
the unowned window with the WS_EX_TOOLWINDOW extended style.
But, at least, in wine it doesn't work. Well, I hope this is a bug :)
#include <windows.h>
#include <stdio.h>
#define IDC_MAIN_EDIT 101
HWND hBackWnd;
void DrawInWindow(HWND hWndToPaint){
HDC hdc = GetDC(hWndToPaint);
if(!hdc)printf("Invalid handle\n");
HPEN hPen = CreatePen(PS_SOLID,5,RGB(0, 0, 255));
SelectObject(hdc, hPen);
static float x=620, y=1, tg=0.5, ctg=2;
static int Xone = 1, Yone = 1;//depending on later recalculation this may become negative
MoveToEx(hdc,(int)x,(int)y,NULL);
if(tg<1){
y+=tg;
x+=Xone;
}else{
y+=Yone;
x+=ctg;
}
if(!LineTo(hdc, (int)x, (int)y) )printf("There are paint problem\n");
ReleaseDC(hWndToPaint,hdc);
//Now recalculate direction
RECT WndRect;
GetClientRect(hWndToPaint,&WndRect);
if(x>=WndRect.right){
if(ctg>0)ctg*=-1;//make negative
Xone=-1;
}
if(x<=WndRect.left){
if(ctg<0)ctg*=-1;//make positive
Xone=1;
}
if(y>=WndRect.bottom){
if(tg>0)tg*=-1;//make negative
Yone=-1;
}
if(y<=WndRect.top){
if(tg<0)tg*=-1;//make positive
Yone=1;
}
}
LRESULT __stdcall MyMainCallBckProcedure( HWND window, unsigned msg, WPARAM wp, LPARAM lp ){
switch(msg){
case WM_KEYDOWN:
if(wp == VK_ESCAPE)PostQuitMessage(0);
break;
case WM_DESTROY:
printf("\ndestroying window\n");
PostQuitMessage(0);
return 0;
case WM_SIZE:
HWND hEdit;
RECT rcClient;
GetClientRect(window, &rcClient);
hEdit = GetDlgItem(window, IDC_MAIN_EDIT);
SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
break;
case WM_WINDOWPOSCHANGED:{//LPARAM is a ptr to WINDOWPOS
RECT BckWndRect;
if(!GetWindowRect(hBackWnd, &BckWndRect) )printf("ERR: getting backwnd rectangle\n");
bool IsRepaint;
WINDOWPOS* pNewPos = (WINDOWPOS*)lp;
if(BckWndRect.left+BckWndRect.right != pNewPos->cx
|| BckWndRect.top+BckWndRect.bottom != pNewPos->cy)IsRepaint = true;
else IsRepaint = false;
MoveWindow(hBackWnd, pNewPos->x, pNewPos->y, pNewPos->cx, pNewPos->cy, IsRepaint);
break;
}
default:
return DefWindowProc( window, msg, wp, lp ) ;
}
}
WNDPROC lpEditWndProc;
LRESULT CALLBACK MyEditCallBckProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
if( (uMsg == WM_CHAR) && (wParam == VK_ESCAPE) )
{
PostQuitMessage(0);
return 0;
}
DrawInWindow(hBackWnd);
lpEditWndProc(hWnd, uMsg, wParam, lParam);
}
bool CreateWindows(){
//creating back window
const char* backwnd = "backwnd";
WNDCLASSEX backwndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, MyMainCallBckProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW+1),
0, backwnd, LoadIcon(0,IDI_APPLICATION) };
if(RegisterClassEx(&backwndclass)<0){
printf("ERR: in registering second window class\n");
return false;
}
hBackWnd = CreateWindowEx( 0, backwnd, "title", WS_EX_TOOLWINDOW |
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
640, 480, 0, 0, GetModuleHandle(0), 0 );
if(!hBackWnd){
printf("ERR: in creating background window\n");
return false;
}
ShowWindow( hBackWnd, SW_SHOWDEFAULT );
//Creating front window
const char* const frontwnd = "frontwnd";
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, MyMainCallBckProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW+1),
0, frontwnd, LoadIcon(0,IDI_APPLICATION) };
if(RegisterClassEx(&wndclass)<0){
printf("ERR: in registering foreground window class\n");
return false;
}
HWND window = CreateWindowEx( 0, frontwnd, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
640, 480, 0, 0, GetModuleHandle(0), 0 );
if(!window){
printf("ERR: in creating foreground window\n");
return false;
}
ShowWindow( window, SW_SHOWDEFAULT );
//creating textbox
HWND hEdit = CreateWindowEx( 0, "edit", "", WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL
| ES_MULTILINE | ES_AUTOVSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, 640,
480, window, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(0), 0 );
HFONT hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
//Let's try to catch some messages in TextBox...
lpEditWndProc = (WNDPROC)SetWindowLongPtr(hEdit, GWL_WNDPROC, (LONG_PTR)&MyEditCallBckProcedure);
//Making foreground window transparent
SetWindowLongPtr(window,GWL_EXSTYLE, WS_EX_LAYERED | GetWindowLongPtr(window, GWL_EXSTYLE) );
SetLayeredWindowAttributes(window, 0, (255*50)/100, LWA_ALPHA);
return true;
//###
}
int main(){
if(!CreateWindows() ){printf("Something gone wrong\n");return 1;}
MSG msg;
while(GetMessage(&msg,0,0,0) ){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
i am working on my first win32 GUI application and i want to send message to the ListBox to add text but the text appears in chines character in the ListBox. The same thing happened to Combo Box
Here is the code :
#include <windows.h>
#include <winbase.h>
#include <stdio.h>
#include "resource.h"
#define DEFAULT_BUTTON_WIDTH 100
#define DEFAULT_BUTTON_HEIGHT 20
HINSTANCE GlobalInstance;
HWND Window;
HWND bCreateWall;
HMENU Menu;
HMENU PopupMenu;
LRESULT CALLBACK MapDetailsDlgProc(HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
SetDlgItemText (hWnd, IDC_MAP_DETAILS_NAME, L"Map Name");
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_ADDSTRING,0, (LPARAM)"Erase Me");
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_RESETCONTENT,0, 0);
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_ADDSTRING,0, (LPARAM)"Exit");
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_ADDSTRING,0, (LPARAM)"Get Fragged");
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_SETCURSEL,0, 1);
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_ADDSTRING,0, (LPARAM)"Erase Me");
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_RESETCONTENT,0, 0);
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_ADDSTRING,0, (LPARAM)"Single Player");
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_ADDSTRING,0, (LPARAM)"Multi Player");
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_SETCURSEL,0, 1);
} break;
case WM_COMMAND:
{
if (wParam == IDOK)
{
long level_rule = SendDlgItemMessage (hWnd,IDC_MAP_DETAILS_LEVEL_RULES, LB_GETCURSEL, 0, 0);
long level_type = SendDlgItemMessage (hWnd,IDC_MAP_DETAILS_LEVEL_TYPE, CB_GETCURSEL, 0, 0);
char temp[500];
sprintf (temp, "Level Type: %i\r\nLevel Rule: %i\r\nOK Button!",level_type, level_rule);
MessageBox (hWnd, (LPCWSTR)temp, L"OK", MB_OK);
EndDialog (hWnd, 0);
}else if (wParam == IDCANCEL)
{
MessageBox (hWnd, L"Cancel Button!", L"Cancel", MB_OK);
EndDialog (hWnd, 0);
}
} break;
}
return (0);
}
void WMCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (lParam == (LPARAM)bCreateWall) MessageBox (Window, L"You PressedbCreateWall", L"Congrats!", MB_OK);
else if (wParam == ID_FILE_EXIT) PostQuitMessage(0);
else if (wParam == ID_DRAWING_WIREFRAME)
{
CheckMenuItem (Menu, ID_DRAWING_WIREFRAME, MF_CHECKED);
CheckMenuItem (Menu, ID_DRAWING_SOLID, MF_UNCHECKED);
}
else if (wParam == ID_DRAWING_SOLID)
{
CheckMenuItem (Menu, ID_DRAWING_SOLID, MF_CHECKED);
CheckMenuItem (Menu, ID_DRAWING_WIREFRAME, MF_UNCHECKED);
}
else if (wParam == ID_MAP_DETAILS) DialogBox (GlobalInstance,MAKEINTRESOURCE(IDD_MAP_DETAILS), NULL, (DLGPROC)MapDetailsDlgProc);
else if (wParam == ID_POPUP_MOVE) MessageBox (Window, L"Move", L"Click", MB_OK);
else if (wParam == ID_POPUP_DELETE) MessageBox (Window, L"Delete", L"Click",MB_OK);
else if (wParam == ID_POPUP_TEXTURE) MessageBox (Window, L"Texture", L"Click",MB_OK);
else if (wParam == ID_POPUP_DUPLICATE) MessageBox (Window, L"Duplicate",L"Click", MB_OK);
}
void DisplayPopupMenu(long x, long y)
{
HMENU temp = GetSubMenu(PopupMenu, 0);
TrackPopupMenu(temp, TPM_LEFTALIGN|TPM_RIGHTBUTTON, x, y, 0, Window, NULL);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY: PostQuitMessage(0); break;
case WM_COMMAND: WMCommand (hWnd, msg, wParam, lParam); break;
case WM_RBUTTONUP: DisplayPopupMenu(LOWORD(lParam), HIWORD(lParam)); break;
}
return (DefWindowProc(hWnd, msg, wParam, lParam));
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevious, LPSTR lpCmdString,int CmdShow)
{
GlobalInstance = hInstance;
WNDCLASS wc;
MSG msg;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = L"ME";
wc.lpszMenuName = NULL;
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&wc))
{
MessageBox (NULL,L"Error: Cannot Register Class",L"ERROR!", MB_OK);
return (0);
}
Window = CreateWindow(L"ME", L"Map Editor", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480, NULL, NULL, hInstance, NULL);
if (Window == NULL)
{
MessageBox (NULL,L"Error: Failed to Create Window", L"ERROR!", MB_OK);
return (0);
}
bCreateWall = CreateWindow(L"BUTTON", L"Create Wall", WS_CHILD | WS_VISIBLE,0, 100, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT, Window,NULL, hInstance, NULL);
Menu = LoadMenu (hInstance, MAKEINTRESOURCE(IDR_MENU));
SetMenu (Window, Menu);
PopupMenu = LoadMenu (hInstance, MAKEINTRESOURCE(IDR_POPUP_MENU));
while (1)
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage (&msg);
}
}
return (1);
}
i think the problem is with (lparam)
How can i fix this problem ????
Well it seems to me that you're using the Unicode API, therefore you would have to pass UTF-16 strings using L"" syntax:
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_ADDSTRING,0, (LPARAM) L"Erase Me");
SendDlgItemMessage (hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_ADDSTRING,0, (LPARAM) L"Exit");
And so on
Here's something I learned the hard way: the Unicode string (LPARAM of LB_ADDSTRING message) must be on a doubleword boundary.
If you are adding from a non-aligned variable, copy it to a buffer first.
There's two days I'll never get back.
I would like to add an About dialog to my Win32 application (developed using C++). How can I add a hyperlink to the dialog? I'm loading the dialog from a resource file (.rc). Is it possible to define this functionality from the .rc file?
My .rc file now looks like this:
IDD_ABOUTBOX DIALOGEX 0, 0, 218, 118
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTER
CAPTION "About My App"
FONT 8, "MS Shell Dlg"
BEGIN
ICON IDI_APP_ICON,IDC_STATIC,13,88,15,15
LTEXT "MY url http://www.myurl.com",IDC_STATIC,15,6,194,24,SS_NOPREFIX
DEFPUSHBUTTON "OK",IDOK,95,98,50,14,WS_GROUP
END
You can use a SysLink Control on Windows XP or above.
You can define it from the .rc file like this:
In resource.rc:
CONTROL "<a>Link</a>",IDC_SYSLINK1,"SysLink",WS_TABSTOP,7,7,53,12
In resource.h:
#define IDC_SYSLINK1 1001
Best way to do the highlighting without any external libraries, still looks and feels the same way any control would do it, even makes the mouse cursor into a finger pointing icon.
/* Start of HyperLink URL */
#define PROP_ORIGINAL_FONT TEXT("_Hyperlink_Original_Font_")
#define PROP_ORIGINAL_PROC TEXT("_Hyperlink_Original_Proc_")
#define PROP_STATIC_HYPERLINK TEXT("_Hyperlink_From_Static_")
#define PROP_UNDERLINE_FONT TEXT("_Hyperlink_Underline_Font_")
LRESULT CALLBACK _HyperlinkParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK _HyperlinkProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static void CreateHyperLink(HWND hwndControl);
/* End of HyperLink URL */
static void CreateHyperLink(HWND hwndControl)
{
// Subclass the parent so we can color the controls as we desire.
HWND hwndParent = GetParent(hwndControl);
if (NULL != hwndParent)
{
WNDPROC pfnOrigProc = (WNDPROC)GetWindowLong(hwndParent, GWL_WNDPROC);
if (pfnOrigProc != _HyperlinkParentProc)
{
SetProp(hwndParent, PROP_ORIGINAL_PROC, (HANDLE)pfnOrigProc);
SetWindowLong(hwndParent, GWL_WNDPROC, (LONG)(WNDPROC)_HyperlinkParentProc);
}
}
// Make sure the control will send notifications.
DWORD dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
SetWindowLong(hwndControl, GWL_STYLE, dwStyle | SS_NOTIFY);
// Subclass the existing control.
WNDPROC pfnOrigProc = (WNDPROC)GetWindowLong(hwndControl, GWL_WNDPROC);
SetProp(hwndControl, PROP_ORIGINAL_PROC, (HANDLE)pfnOrigProc);
SetWindowLong(hwndControl, GWL_WNDPROC, (LONG)(WNDPROC)_HyperlinkProc);
// Create an updated font by adding an underline.
HFONT hOrigFont = (HFONT)SendMessage(hwndControl, WM_GETFONT, 0, 0);
SetProp(hwndControl, PROP_ORIGINAL_FONT, (HANDLE)hOrigFont);
LOGFONT lf;
GetObject(hOrigFont, sizeof(lf), &lf);
lf.lfUnderline = TRUE;
HFONT hFont = CreateFontIndirect(&lf);
SetProp(hwndControl, PROP_UNDERLINE_FONT, (HANDLE)hFont);
// Set a flag on the control so we know what color it should be.
SetProp(hwndControl, PROP_STATIC_HYPERLINK, (HANDLE)1);
}
LRESULT CALLBACK _HyperlinkParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WNDPROC pfnOrigProc = (WNDPROC)GetProp(hwnd, PROP_ORIGINAL_PROC);
switch (message)
{
case WM_CTLCOLORSTATIC:
{
HDC hdc = (HDC)wParam;
HWND hwndCtl = (HWND)lParam;
BOOL fHyperlink = (NULL != GetProp(hwndCtl, PROP_STATIC_HYPERLINK));
if (fHyperlink)
{
LRESULT lr = CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam);
SetTextColor(hdc, RGB(0, 0, 192));
return lr;
}
break;
}
case WM_DESTROY:
{
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)pfnOrigProc);
RemoveProp(hwnd, PROP_ORIGINAL_PROC);
break;
}
}
return CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam);
}
LRESULT CALLBACK _HyperlinkProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WNDPROC pfnOrigProc = (WNDPROC)GetProp(hwnd, PROP_ORIGINAL_PROC);
switch (message)
{
case WM_DESTROY:
{
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)pfnOrigProc);
RemoveProp(hwnd, PROP_ORIGINAL_PROC);
HFONT hOrigFont = (HFONT)GetProp(hwnd, PROP_ORIGINAL_FONT);
SendMessage(hwnd, WM_SETFONT, (WPARAM)hOrigFont, 0);
RemoveProp(hwnd, PROP_ORIGINAL_FONT);
HFONT hFont = (HFONT)GetProp(hwnd, PROP_UNDERLINE_FONT);
DeleteObject(hFont);
RemoveProp(hwnd, PROP_UNDERLINE_FONT);
RemoveProp(hwnd, PROP_STATIC_HYPERLINK);
break;
}
case WM_MOUSEMOVE:
{
if (GetCapture() != hwnd)
{
HFONT hFont = (HFONT)GetProp(hwnd, PROP_UNDERLINE_FONT);
SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, FALSE);
InvalidateRect(hwnd, NULL, FALSE);
SetCapture(hwnd);
}
else
{
RECT rect;
GetWindowRect(hwnd, &rect);
POINT pt = { LOWORD(lParam), HIWORD(lParam) };
ClientToScreen(hwnd, &pt);
if (!PtInRect(&rect, pt))
{
HFONT hFont = (HFONT)GetProp(hwnd, PROP_ORIGINAL_FONT);
SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, FALSE);
InvalidateRect(hwnd, NULL, FALSE);
ReleaseCapture();
}
}
break;
}
case WM_SETCURSOR:
{
// Since IDC_HAND is not available on all operating systems,
// we will load the arrow cursor if IDC_HAND is not present.
HCURSOR hCursor = LoadCursor(NULL, IDC_HAND);
if (NULL == hCursor)
hCursor = LoadCursor(NULL, IDC_ARROW);
SetCursor(hCursor);
return TRUE;
}
}
return CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam);
}
Here is how to use it:
CreateHyperLink(GetDlgItem(Dialog_HWND_GOES_HERE, STATIC_TEXT_IDENIFIER_GOES_HERE));
Where the static label can get clicked in the main dialogs subclass do something like this..
if (HIWORD(wParam) == BN_CLICKED) { //Buttons, checkboxs, labels, static labels clicked
switch (LOWORD(wParam))
{
case STATIC_TEXT_IDENIFIER_GOES_HERE:
ShellExecute(NULL, "open", "http://www.google.com", NULL, NULL, SW_SHOWNORMAL);
break;
}
}