Output text into a textbox C++ - c++

I've been googling for a while and I found nothing working for me so I'm here asking you folks this question.
I've already tried with SendMessage, SetWindowText and much more.
What I am trying to do is output a text in a textbox ( TEXT("edit") ... ).
The messages I have to display are: "You win", "You lose" or "Draw".
What do you suggest me to do?
(I'm using DEV C++)
Thanks everybody!

Your code snippet:
HWND hwndbutton[2];
switch (message) /* handle the messages */
{
case WM_CREATE:
hwndbutton[0] = CreateWindow(TEXT("edit"),TEXT(""), WS_VISIBLE | WS_CHILD |
WS_BORDER,10,10,50,30, hwnd, (HMENU)11,0,0);
looks like it is inside a window procedure - first problem is that the value in hwndbutton[0] will be lost (it's on the stack) when the procedure is called again. You could, for example, make it static:
static HWND hwndbutton[2];
Tracing through your debugger should show you this.

Related

Can't show/hide buttons in the main window of my C++ Win32 app [duplicate]

This question already has answers here:
Access a variable from a different switch case (from WM_CREATE to WM_CTLCOLORSTATIC in the WinApi)
(2 answers)
Closed last month.
I have created a basic button in case: WM_CREATE in the windows procedure with the following.
/*The "new_game_button" is declared as type HWND at the
start of the windows procedure function but not initialized.*/
new_game_button = CreateWindow ( "BUTTON", "New Game",
WS_CHILD | WS_BORDER ,
50, 50, 100, 100,
hwnd, NULL, NULL, NULL);
My intent is to create an instructions and "start new game" button as the first thing in my simple tictactoe app. It will immediately show as expected if I give the parameter WS_VISIBLE.
Further in the same case:WM_CREATE if I use the lines
if (!start_Game){ //global variable default is false
ShowWindow( new_game_button, SW_SHOW);
}
The button will show as expected.
Outside of those two cases I cannot get the button to show at a later stage.
Further, if I use one of those two methods to show the button I can never get it to go away using
ShowWindow ( new_game_button, SW_HIDE);
Once the button is showing, it stays for the duration of the programs execution. Doesn't matter which case. Command/Create/Paint
I have tried using
if (start_Game){
ShowWindow( new_game_button, SW_HIDE);
UpdateWindow ( new_game_button );
//UpdateWindow ( hwnd ); tried this as well
}
inside case WM_CREATE.
I have also tried the same SW_HIDE line inside case: WM_COMMAND where a new game is generated (compiles but doesn't hide the button.)
I have tried declaring the button child window outside the WM_CREATE inside the windows procedure function. Then using WM_CREATE to show the window - works -- still WM_COMMAND will not hide the window.
I have also tried creating the button window inside of case:WM_PAINT which works to show the button but not to get rid of it. I have even tried DestroyWindow which just fails. [returns 0]
In trying to understand the behaviour of the button window - I have found that I cannot get
ShowWindow( new_game_button, SW_SHOW);
to work in the case:WM_COMMAND.
You said (in a code comment in the question).
new_game_button is declared as type HWND at the start of the windows procedure function but not initialized.
Each incoming message means a new call to your window procedure. Variables which are local to a function don't retain their value between calls unless they are marked static.
When your window procedure returned from processing WM_CREATE, you lost the value of new_game_button. When you try to use it during WM_COMMAND processing later, it is uninitialized and your program causes undefined behavior by passing it to ShowWindow.
Every comment helped me solve this which I appreciate. I am too new to give reputation sadly.
case WM_CREATE:
{
new_game_button = CreateWindow ("BUTTON", "New Game",
WS_CHILD | WS_BORDER ,
50, 50, 100, 100,
hwnd, (HMENU) 1, NULL, NULL);
if (!start_Game){
ShowWindow( new_game_button, SW_SHOW);
}
}
break;
After I had an ID for the dialog I am able to use GetDlgItem function to show or hide as I please.
new_game_button = GetDlgItem (hwnd, 1);
ShowWindow( new_game_button, SW_HIDE);

Why does c++ send WM_DRAWITEM to the parent process?

I started recently learning C++ and WinAPI, I want to be able to create my own programs
I am subclassing a button (into separate file, because I like things clean and organized - is that a bad idea?), because I want to have few of the kind with same parameters. I also want to draw it, and the question that pops to my mind is: wouldn't it be better to have it all in the class file? Meaning all parameters including custom draw. It is annoying to go to main file to change the looks and set all other parameters in the class file. I use codeblocks.
EDIT (explanation):
#include <Windows.h>
#include <Winuser.h>
#include "CustomButton.h"
/*global vars*/
WNDPROC CustomButton::CustomButtonLongPtr;
/*functions*/
LRESULT CALLBACK CustomButtonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
CustomButton * CustomButton::CreateCustomButton(HINSTANCE hInstance, HWND hwnd, int pos_x, int pos_y, int width, int height)
{
CustomButton * p_CustomButton = new CustomButton;
HWND customButton = CreateWindowEx(0, "BUTTON", "OK", WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, pos_x, pos_y, width, height, hwnd, (HMENU)200, (HINSTANCE)GetWindowLong(hwnd, GWLP_HINSTANCE), p_CustomButton);
if(customButton == NULL)
{
delete p_CustomButton;
MessageBox(NULL, "Problem creating the Search box.", "Error", 0);
return 0;
}
CustomButton::CustomButtonLongPtr = (WNDPROC)SetWindowLongPtr(customButton, GWLP_WNDPROC, (LONG_PTR)&CustomButton::CustomButtonProc);
return p_CustomButton;
}
I want to use WM_DRAWITEM for this button in CustomButtonProc and I am wondering why did the developers think that it would be smarted to allow to use it only in parent WinProc.
This is a little complicated to explain.
You're probably coming from a background where you plug a function into an outlet to handle events, something like
extern void onClicked(void);
button->OnClicked = onClicked;
And while it's fully possible for Windows to have done this from the start, you have to remember that Windows was originally designed to run on systems with severely limited memory, so it was important that controls not waste memory. And there are a lot of events you can get from a button:
void (*OnClicked)(void);
void (*OnDoubleClicked)(void);
void (*OnDisabled)(void);
void (*OnHighlight)(void);
void (*OnKillFocus)(void);
void (*OnPaint)(void);
void (*OnSetFocus)(void);
void (*OnUnhighlight)(void);
void (*OnUnpushed)(void);
HBRUSH (*OnCtlColorButton)(void);
Having these for every button in your program — that is, push buttons, checkboxes, radio buttons, and groupboxes — with most of them likely to be unused would just be a massive waste of memory.
Because Windows needs a way to communicate between the system and a window and between windows, Microsoft decided to create a message-passing interface where each message had a 16-bit code and two pointer-sized (originally one 32-bit and one 16-bit) parameters and a pointer-sized return value. And there aren't a lot of messages that Windows needs for itself, giving both window classes and the application a lot of real estate for using messages to communicate. So why not use a message to signal the event?
Using a message avoids the waste of memory while still allowing the button to pass data to and return data from its target window. So the logic follows that all a button would need to do is
/* this is not the correct syntax but let's use it for expository purposes */
#define BN_CLICKED someNumberHere
case WM_LBUTTONUP:
SendMessage(GetParent(hwnd), BN_CLICKED, hwnd);
break;
and the parent would handle that:
case BN_CLICKED:
if (whichButton == button1)
doButton1Stuff();
break;
No wasted memory, but still flexible and extensible. And even more importantly, also binary-compatible: if more events were added later, the size of the function pointer table would need to change, and newer programs that tried to use newer events on older systems would clobber random memory. With messages, these programs would just have dead code.
Now why send the message to the parent? If we view windows as communication endpoints, then this is obvious: you want the button to tell its parent that it was clicked because you're communicating that the button was clicked!
But more important, you didn't write the button's window procedure. Microsoft did, and they provide the same one to every program. If you could handle the message in the button procedure, where would you put it? You can't change the button procedure, after all.
(Nowadays we have something called "subclassing" which allows you to override a single window's window procedure to do custom processing. It's not used for event handling because it's more work than just sending up to the parent.)
All of this extends to custom draw; just substitute "custom draw" for "clicked" and it should still make sense. Hopefully this explanation was clear, even with that mental substitution.
If you want, you can write your own facility to handle events in the function pointer way. Keep a map of window handles to event functions and call a global dispatch function in all your window procedures to handle the event messages WM_COMMAND, WM_NOTIFY, and (for trackbars) WM_HSCROLL and WM_VSCROLL. How you do this is up to you, but think about whether you really want to do it this way; sometimes it's necessary, but sometimes it isn't. If you do, remember to provide a way to pass arbitrary data to the event function that's decided at event connection time, so the event handler can do something reasonable without relying on global state.
Thanks to comments by RemyLebeau and IInspectable I was able to also find solution to my frustration, which I am going to explain here for anybody else who's scratching their heads over this very issue.
This solution does not require VCL nor any component from Visual Studio and such.
First define your own custom message, in the way that you can reach it inside WndProc:
#define MY_DRAWITEM (WM_APP+1)
UINT uDrawButtonMsg = RegisterWindowMessage(_T("MY_DRAWITEM"));
Then find out what number it is assigned:
std::cout << uDrawButtonMsg; //for example 49648
And send this message from WndProc to your subclassed control from any message you wish, for example WM_DRAWITEM:
case WM_DRAWITEM:
{
::SendMessage(p_CustomButton->customButton, uDrawButtonMsg, wParam, lParam);
break;
}
And then in your subclass just catch the message by the 5 digit number you looked for while ago:
if(49648 == uMsg)
{
//do your DRAWITEM stuff here
}
Thanks to everybody who contributed to this article helping with exaplanation, tips and also historical background!

c++ Dialog box doesn't render properly on PC screen

I have dialog window specified via a *.rc file that doesn't render properly on the screen. It exhibits the following set of anomalies:
The dialog window is white.
The dialog window title bar is absent.
All GUI objects are rendered two times -- once at position (X,Y) specified by the *.rc file and a 2nd time at position (X+3,Y+23). Pushbuttons at position (X,Y) are alive. The "echoes" at (X+3,Y+23) are non-functional.
The pushbutton object specified as DEFPUSHBUTTON is not the default pushbutton, and the pushbutton object specified as PUSHBUTTON is the default pushbutton.
Other than the default pushbutton anomaly and the weird appearance, the Dialog window operates as it should, as does the callback function -- SelectPuzzle() -- that it invokes. The source code for SelectPuzzle() is not enclosed but is available upon request as are screen shots.
This code is virtually identical to code I have used successfully in other projects. Why it doesn't work here remains a mystery. Can anyone help?
I've tried everything I can think of to diagnose this bug but without success, e.g.:
In place of DialogBoxParam(), I tried using DialogBox() with variable PuzzleDB supplied as a global. Same result.
I tried stripped-down, simplified versions both of the resource file and of the SelectPuzzle() function,
-- i.e., a DIALOGEX resource with just a "Cancel" pushbutton and a SelectPuzzle() function with just an empty WM_INITDIALOG section and a WM_COMMAND case to support the Cancel pushbutton. Same result.
I verified consistent use of the IDD_SELECTPUZZLE constant in MainApp and in resource file. I also tried different numeric values for IDD_SELECTPUZZLE.
Same result.
The following code excerpts are relevant:
MainApp.h (included in stdafx.h)
.
.
#define IDD_SELECTPUZZLE 9500
#define IDM_SelectPuzzle 9510
#define ID_CurrentPuzzle 9521
#define ID_SelectedPuzzle 9522
#define ID_PuzzleSelStatus 9523
.
.
PuzzleDB.h (included in stdafx.h)
//=======================================================================
// PuzzleDB.h : Defines the entry point for the application.
//=======================================================================
#pragma once
typedef struct {
int NumberOfPuzzles;
int *PuzzleNumbers;
int ndxCurrentPuzzleNumber;
clasPuzzle *Puzzle;
} PuzzleSelectionData, *pPuzzleSelectionData;
clasPuzzle *ResetPuzzle(
clasPuzzle *Puzzle
);
char *LoadPuzzle(
char *tstr
, int ndxSelectedPuzzle
, pPuzzleSelectionData pPuzzleDB );
MainApp.cpp,
#include "stdafx.h"
.
.
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK SelectPuzzle(HWND, UINT, WPARAM, LPARAM);
.
.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
.
.
static PuzzleSelectionData PuzzleDB;
.
.
switch (message)
.
.
case WM_COMMAND:
switch (wParam)
.
.
//*****WM_COMMAND********************************************
case IDM_SelectPuzzle:
k = PuzzleDB.ndxCurrentPuzzleNumber;
DialogBoxParam(
hInst
, MAKEINTRESOURCE(IDD_SELECTPUZZLE)
, hWnd, SelectPuzzle
, (unsigned long)(&PuzzleDB));
if (PuzzleDB.ndxCurrentPuzzleNumber != k)
SendMessage(hWnd,WM_COMMAND,IDM_LoadPuzzle,0L);
break;
.
.
AppName.rc
.
.
//**** BEGIN Application specific resources *********************************
//--------------------------------------------------------------------------------
// Application specific resource.
// Menu Dialog item "Select Puzzle"
//--------------------------------------------------------------------------------
IDD_SELECTPUZZLE DIALOGEX 4, 4, 126, 74 // Position w.r.t. parent window.
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Select Puzzle"
FONT 10, "MS Shell Dlg"
BEGIN
ICON IDR_MAINFRAME , IDC_STATIC ,14,14, 21,20
LTEXT "Use Mouse Wheel to Select Puzzle." , IDC_STATIC , 8, 4,118,12,SS_NOPREFIX
LTEXT "Current Puzzle: " , IDC_STATIC , 8,16, 52,12,SS_NOPREFIX
LTEXT "New Selection: " , IDC_STATIC , 8,28, 52,12,SS_NOPREFIX
PUSHBUTTON "Accept" , ID_OK , 8,40, 52, 4,WS_GROUP
DEFPUSHBUTTON "CANCEL" , ID_CANCEL ,66,40, 52, 4,WS_GROUP
LTEXT " " , ID_CurrentPuzzle ,66,16, 52,12,SS_NOPREFIX
LTEXT " " , ID_SelectedPuzzle ,66,28, 52,12,SS_NOPREFIX
LTEXT " " , ID_PuzzleSelStatus, 8,60,110,12,SS_NOPREFIX
END
//**** END Application specific resources ***********************************
The main problem is that you return TRUE from the dialog procedure for all messages. Except for a handful of special messages, this indicates that you don't want default handling. Thus things that should be done, are not being done.
Tip for dialogs: seriously underdocumented, but where you need to return some specific value for some specific message, use SetDlgMsgResult from <windowsx.h>, or equivalent code.
In passing, the code can be greatly simplified and improved by
removing use of Visual C++ non-standard semantics precompiled headers (for standard-conformance and maintainability),
removing use of Visual C++ non-standard tWinMain, just use standard main,
removing use of Windows 9x support (the unmentionably silly Microsoft T stuff for strings),
using std::wstring instead of C library string handling,
and using wide string literals instead of narrow ones plus conversion,
etc.
A particularly bad apple, in the tWinMain function this code:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
InitInstance only makes sense for 16-bit Windows.
passing nCmdShow around only makes sense for 16-bit Windows (in 32-bit Windows it is ignored by the first ShowWindow call).
Returning FALSE here erroneously indicates success, when it is a failure.
I have seen essentially this code many times, even in the D language's Windows support, and I suspect that it originates with Microsoft.
Anyway, wherever you got that from, that source is seriously outdated and unreliable, to be treated only as a source of bad programming habits and ingenious ways to introduce bugs.

c++ mfc: update HWND through a control box

Can anyone help me how I update a HWND value through an edit control or any other kind of text box? I tried the following
void ChwndtestDlg::OnBnClickedButton1()
{
TCHAR thebuffer[100];
HWND thetext = (HWND)thebuffer;
GetDlgItemText(IDC_EDITWINDOW, thebuffer, 100);
::SendMessage(thetext,WM_SETTEXT,0,(LPARAM)L"hello");
}
But, that does not work! I'm new to all of this, and I'll be grateful for any help. Please bear in mind that I already know about enumwindows, and I have already successfully changed text in another program from my program, but I want to actually update the HWND in my edit control. It is supposed to work like so...
program 2's current hwnd = 0x00000:
open my program -> open program #2 -> input 0x00000 into textbox in my program -> click button in my program to update the hwnd value -> input text in my programs text editor -> text goes to program 2's text editor. I'm aware that there are other ways of doing this, but I would really like to do it the way I have described. Thanks in advance. I found a similar question, but the answer was to use enumwindows, but I don't want to use that.
You are typecasting the TCHAR[] itself to an HWND. That will never work. You need to extract the TCHAR[] text from the edit control, then use _stscanf() or similar parsing function to convert that text value to an integer which can be typecasted to an HWND, then assign your other text to that HWND as needed.
For example:
void ChwndtestDlg::OnBnClickedButton1()
{
CString sWnd;
if (GetDlgItemText(IDC_HWNDEDIT, sWnd) > 0)
{
HWND hWnd;
if (_stscanf((LPTSTR)sWnd, _T("%p"), &hWnd) == 1)
{
CString sText;
GetDlgItemText(IDC_TEXTEDIT, sText);
::SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)(LPTSTR)sText);
}
}
}

How to create additional controls in WinAPI? Only the first control works?

I've recently started to study WinAPI. After going through about ten top search results for tutorials on it, I'm still confused where you add code for more than one control per window? For example, if I want to add a second button, what kind of code and where do you place the code for it?
When I #define IDC_BUTTON WM_USER + 1, add HINSTANCE hIns; and HWND hButton; to the Callback, and then call this:
case WM_CREATE:
hIns=((LPCREATESTRUCT)lParam)->hInstance;
hButton=CreateWindow("Button","Click Me",WS_CHILD|WS_VISIBLE,70,60,150,30,hwnd,(HMENU)IDC_BUTTON,hIns,0);
break;
It works and the button appears in the window. But when I try to add a second one, nothing appears, even with changed names:
#define IDC_BUTTON2 WM_USER + 2
+
HINSTANCE hIns;
HWND hButton2;
case WM_CREATE:
hIns=((LPCREATESTRUCT)lParam)->hInstance;
hButton=CreateWindow("Button","Click Me",WS_CHILD|WS_VISIBLE,70,60,150,30,hwnd,(HMENU)IDC_BUTTON,hIns,0);
hButton2=CreateWindow("Second","Press here",WS_CHILD|WS_VISIBLE,170,160,250,130,hwnd,(HMENU)IDC_BUTTON2,hIns,0);
break;
The first button appears OK, but the second does not (different coordinates also). What am I doing wrong here? Thanks!
Edit:
I replaced the hIns2 with hIns in the code.
hButton2=CreateWindow("Second","Press here",WS_CHILD|WS_VISIBLE,...);
Let's tackle this at the core. The fundamental thing you are doing wrong is completely ignoring the need to check for errors. CreateWindow() returns NULL when it failed. GetLastError() then returns an error code that indicates the problem. That same error code is also visible in a debugger with the "#err" pseudo variable.
You would then quickly have discovered that you got error 1407, described like this in the WinError.h SDK header:
//
// MessageId: ERROR_CANNOT_FIND_WND_CLASS
//
// MessageText:
//
// Cannot find window class.
//
#define ERROR_CANNOT_FIND_WND_CLASS 1407L
Which makes it crystal clear that you flubbed the class name in the CreateWindow() call.
Never skip error checks, especially when you are just starting out with winapi programming. It isn't just useful to let programs graciously fail when things go wrong on the user's machine, it is clearly also extremely useful to diagnose bugs in your code.
First of all there is no class name called "SECOND unless you defined one already so if you want to make say 10 buttons the first parameter in the CreateWindow function is going to be "BUTTON" in all of them, you can also change it to "EDIT" if you want an editable text box or "STATIC" if you ant to put a static box.
Secondly you can make a process of adding buttons alot more easier if you followed this note:
Instead of defining your button by making
#define IDB_BUTTON WM_USER + 2
and then inserting the IDB_BUTTON into the CreateWindow function as (HMENU)IDB_BUTTON
you can simply just write (HMENU)<any number of your choice> in to the CreateWindow function just like (HMENU) 2 without needing to predefine that number using #define and then when you want to make an action when the button is pressed you can just pass that number in a case of a switch statement that has (LOWORD(wParam)) as its switch .
It seems confusing but see the code to understand what i mean
full code in your procedure:
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_CREATE:
hButton=CreateWindow("Button","Click Me",WS_CHILD|WS_VISIBLE,70,60,150,30,hWnd,(HMENU) 1,NULL,NULL);
hButton2=CreateWindow("BUTTON","Press here",WS_CHILD|WS_VISIBLE,170,160,250,130,hwnd,(HMENU) 2,NULL,NULL);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case 1:
//What will the first button do?write it here
break;
case 2:
//What will the second button do?write it here
break;
}
break;
}
return 0;
}
Good luck on your path studying win32 c++ i remember when i started also it was confusing and it is still for me but by hard work you will master it
;)