Win32 edit control default text - c

(NB: This is probably more of a programming style / architecture question)
When the main window is created (but not yet shown), my window procedure receives WM_CREATE; this is where I call CreateWindow for the edit control:
case WM_CREATE:
hwndEdit = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("edit"), L"Default text",
WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL,
10, 10, 150, 24, hWnd, (HMENU)ID_EDIT,
hInst, NULL);
break;
and as expected "Default text" shows up in the edit control.
I know I can also use SendMessage or SetWindowText.
So, I have three API calls to do what I want - which one should I be using?
best,
Chris

If it is easy and convenient to set the text in CreateWindowEx, then do so.
If, for some reason, it is not convenient, then use SetWindowText.
In this case you probably don't want to use L"Default Text" as the default text in CreateWindowEx.
Since lpWindowName is optional, you may pass NULL to leave it blank.
Alternatively, you might use something which makes more sense for your application, such as L"(Loading...)".

Related

Hiding/Showing Child Windows of a Tab Control Win32 [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
To be clear, I am coding in win32 and am not using MFC, wxWidgets or .net.
My issue is that I have a tab control with 2 tabs. For debugging purposes, each tab has a single STATIC window. When initialising, the following code is run:
createTabControl();
CreateStaticViewTab1();
CreateStaticViewTab1();
ShowWindow(Task1Tab, SW_SHOW);
Where
void createTabControl(){
TCITEM tie = { 0 };
hWndInputTab = CreateWindow(WC_TABCONTROL, L"Input", WS_VISIBLE | WS_CHILD , 10, 40, 300, 650, hWnd, (HMENU)TAB_INPUT, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
SetDefaultFont(hWndInputTab);
tie.mask = TCIF_TEXT;
TCHAR pszTab1[] = L"TAB 1";
tie.pszText = pszTab1;
TabCtrl_InsertItem(hWndInputTab, 0, &tie)
TCHAR pszTab2[] = L"TAB 2";
tie.pszText = pszTab2;
TabCtrl_InsertItem(hWndInputTab, 1, &tie)
}
void CreateStaticViewTab1(){
Task1Tab = CreateWindowEx(0,L"STATIC",L"Static Control on Tab1",WS_CHILD | WS_BORDER | SS_CENTER | SS_CENTERIMAGE, 75, 75, 200, 60, hWndInputTab,NULL, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),NULL);
SetDefaultFont(Task1Tab);
}
void CreateStaticViewTab2(){
Task1Tab = CreateWindowEx(0,L"STATIC",L"Static Control on Tab2",WS_CHILD | WS_BORDER | SS_CENTER | SS_CENTERIMAGE, 75, 75, 200, 60, hWndInputTab,NULL, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),NULL);
SetDefaultFont(Task2Tab);
}
In the WndProc, I am handling the WM_NOTIFY message. I have checked and can confirm that it executes correctly, calling the appropriate functions (ShowTab1() and ShowTab2()).
These two functions are designed to show and hide the appropriate tabs when the selection changes. They do so by the following:
void ShowTab1(){
ShowWindow(Task2Tab, SW_HIDE);
ShowWindow(Task1Tab, SW_SHOW);
}
void ShowTab2(){
ShowWindow(Task1Tab, SW_HIDE);
ShowWindow(Task2Tab, SW_SHOW);
}
These should - as I understand it - hide and show the correct tabs as appropriate.
My issue is that when the program is loaded, the correct tab (1) is shown. When tab 2 is clicked, the content of tab 1 (Task1Tab) is correctly hidden, however, the content of tab 2 (Task2Tab) is not correctly shown. When returning to tab 1, Task1Tab is correctly shown.
I cannot identify why there is a difference between the two pieces of code, as they are virtually identical.
nb. I have tested the code without the ShowWindow(Task1Tab, SW_SHOW) in the initialisation, this creates the tabs without any content and when tab 2 is clicked, nothing is shown, however, when tab 1 is clicked, Task1Tab is correctly shown.
You appear to have been caught out by some routine copy/paste errors. You call CreateStaticViewTab1 twice and never call CreateStaticViewTab2. And both CreateStaticViewTab1 and CreateStaticViewTab2 assign to Task1Tab. These mistakes would explain the behaviour that you observe.
Were your code to have performed any error checking, then that would have led you to the problem. Checking for errors would have revealed that ShowWindow(Task2Tab, ...) was failing because of an invalid window handle. So, another important lesson, beyond taking more care with the clipboard, is that you should always check for errors when calling Windows API functions.
Obvious issue - CreateStaticViewTab2() was never called.

GtkAboutDialog icon not loading?

I'm attempting to add an about dialog to my next bit of tutorial code, but I can't get the icon to load for some reason. Below is the entire function for creating and displaying the dialog.
static void help_clicked(GtkButton *button, GtkWindow *window)
{
const gchar *authors[] = { "me", NULL };
const gchar *license = "somestuff";
GdkPixbuf *logo = gdk_pixbuf_new_from_file("logo.png", NULL);
gtk_show_about_dialog(window,
"authors", authors, "license", license, "license-type", GTK_LICENSE_CUSTOM,
"logo", logo, "logo-icon-name", "Logo Icon",
"program-name", "Chapter 6, Exercise 1",
"version", "1.0",
"comments", "This is just an exercise from Chapter 6 of the book I'm reading.",
"website", "http://www.google.com", "website-label", "Application Homepage",
"copyright", "(C) 2014 Patrick Meyer",
"wrap-license", TRUE, NULL);
}
This results in an about dialog with every attribute successfully set except the icon.
The weird thing is, the exact same call to gdk_pixbuf_new_from_file() works in main() when I supply it to gtk_window_set_icon(). This is a single-file program with logo.png present in the directory of execution. What's missing?
as the API reference clearly states, the GtkAboutDialog:logo-icon-name property overrides the GtkAboutDialog:logo property:
https://developer.gnome.org/gtk3/stable/GtkAboutDialog.html#GtkAboutDialog--logo-icon-name
also, you're passing a value for the logo-icon-name property that does not mean anything; the logo-icon-name property requires a named icon according to the Icon Naming Specification.
just remove the logo-icon-name property and you'll see the correct icon.
as a side note from your example: you should release the reference on the GdkPixbuf object you create after gtk_show_about_dialog() returns, otherwise you will leak it. ideally, though, since you don't want to load the image file from disk every time you click the help button, you should use something like this:
static GdkPixbuf *logo_icon = NULL;
if (logo_icon == NULL)
logo_icon = gdk_pixbuf_new_from_file ("logo.png", NULL);
gtk_show_about_dialog (...);
which will keep the pixbuf around for the duration of your application.
another option is to use GResource and inject the image data into the application's binary.
The problem is you are setting logo-icon-name too which is supposed to be a symbolic name for an icon, not a human description.
So the internal image is being set correctly and then replaced internally a second time. This also explains why calling gtk_window_set_icon() afterwards works correctly.
The problem is with the logo-icon-name property. As it is stated inside the documentation, this overwrites the logo property. If you leave out the logo-icon-name property, the logo will show correctly.

simple c programming gui

I developed the steam table equation solver in C language...but the inputing the values in black screen console is boring.
So I strictly wanted to create simple GUI in C.
I searched for hello world codes, all were pretty long. But this was the only one I understood.
#include <windows.h>
int main()
{
MessageBoxA( NULL, "Hello World!", "Hello", MB_OK );
}
By using a gui builder for C, i got this code, now I was thinking how to scan values from TEXTBOX1 and TEXTBOX2 on Clicking of COMMANDBUTTON1 and display the output in TEXTBOX3?
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include "hello.auto.h"
HWND hwnd_Label1, hwnd_Label2, hwnd_TextBox1, hwnd_TextBox2, hwnd_CommandButton1,
hwnd_TextBox3;
HFONT MSSansSerif_8pt;
void CreateChildWindows(HWND hwndMainWindow, HINSTANCE hInstance)
{
InitCommonControls();
MSSansSerif_8pt = CreateFont(-11,0,0,0,FW_NORMAL,0,0,0,0,0,0,0,0,"MS Sans Serif");
hwnd_Label1 = CreateWindowEx(0, "Static", "Pressure",
WS_CHILD | WS_VISIBLE,
11, 55, 95, 38, hwndMainWindow,
(HMENU)Label1, hInstance, NULL);
SetWindowFont(hwnd_Label1, MSSansSerif_8pt, TRUE);
hwnd_Label2 = CreateWindowEx(0, "Static", "Temperature",
WS_CHILD | WS_VISIBLE,
11, 110, 95, 38, hwndMainWindow,
(HMENU)Label2, hInstance, NULL);
SetWindowFont(hwnd_Label2, MSSansSerif_8pt, TRUE);
hwnd_TextBox1 = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit" , NULL,
WS_CHILD | ES_WANTRETURN | WS_VISIBLE,
187, 55, 83, 35, hwndMainWindow,
(HMENU)TextBox1, hInstance, NULL);
SetWindowFont(hwnd_TextBox1, MSSansSerif_8pt, TRUE);
hwnd_TextBox2 = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit" , NULL,
WS_CHILD | ES_WANTRETURN | WS_VISIBLE,
187, 99, 83, 35, hwndMainWindow,
(HMENU)TextBox2, hInstance, NULL);
SetWindowFont(hwnd_TextBox2, MSSansSerif_8pt, TRUE);
hwnd_CommandButton1 = CreateWindowEx(0, "Button", "CommandButton1",
WS_CHILD | BS_MULTILINE | BS_PUSHBUTTON | WS_VISIBLE,
308, 77, 117, 52, hwndMainWindow,
(HMENU)CommandButton1, hInstance, NULL);
SetWindowFont(hwnd_CommandButton1, MSSansSerif_8pt, TRUE);
hwnd_TextBox3 = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit" , NULL,
WS_CHILD | ES_WANTRETURN | WS_VISIBLE,
66, 220, 385, 35, hwndMainWindow,
(HMENU)TextBox3, hInstance, NULL);
SetWindowFont(hwnd_TextBox3, MSSansSerif_8pt, TRUE);
return;
}
HWND GetItem(int nIDDlgItem)
{
switch(nIDDlgItem)
{
case -1:
return GetParent(hwnd_Label1);
case Label1:
return hwnd_Label1;
case Label2:
return hwnd_Label2;
case TextBox1:
return hwnd_TextBox1;
case TextBox2:
return hwnd_TextBox2;
case CommandButton1:
return hwnd_CommandButton1;
case TextBox3:
return hwnd_TextBox3;
default: return NULL;
}
}
void Form_Unload(HWND hMainWnd)
{
DeleteFont(MSSansSerif_8pt);
return;
}
I tried many times, but failed. Even if you people give me links of good sites, then I will be greatful.
You're looking for a good book on Win32 API programming using C. And you're in luck, there's a great book that pretty much everyone uses to learn it. It's written by Charles Petzold, and it's called (aptly enough) Programming Windows. You want the 5th edition, which is the most recent version that discusses Win32 programming.
There are also various tutorials available online if you search for "Win32 programming". However, a number of them contain some errors and misunderstandings (like the difference between ANSI and Unicode strings), and the good ones are rather short and incomplete. You won't learn everything you need to know to write a non-trivial program from online tutorials, but you should be able to get something really simple up on the screen. This one by theForger is one I've seen recommended many times.
Be warned, though, that writing GUI code (especially at such a low level) tends to be a lot more verbose than simply getting text onto the screen for a console program. You're going to end up writing a bunch of code that is used only to make the GUI work and has nothing to do with the logic of your program. It's much easier if you learn the C language first, and that's best done through simple console-type, text-only programs.
As for your specific question, you've created three textbox controls on the screen, named hwnd_TextBoxX, where X is a number between 1 and 3. As you probably already know, hwnd indicates a handle to a window (wnd), and so those variables hold handles to the textbox windows.
The Win32 API provides a GetWindowText function, which you can use to retrieve the text from a particular window. You pass it a handle to the desired window (hWnd), a pointer to a character buffer, and an integer value indicating the length of your buffer. Already, the ugly nature of the C language crops up—you have to understand how strings work in C in order to call the function correctly.
Once you've retrieved the string displayed in one of the textboxes, you can display it in another textbox window using the similar SetWindowText function, which takes only the window handle (hWnd) and a pointer to the buffer containing the string.
The code would look something like this:
// Get the text displayed in textbox 1
TCHAR szBuffer[100];
GetWindowText(hwnd_TextBox1, szBuffer, 100);
// Display that text in textbox 3
SetWindowText(hwnd_TextBox3, szBuffer);
To do this in response to a click on a button, you'll need to learn about the Win32 equivalent of "events"—window messages. Child windows, like button controls, send notification messages to their parent window (i.e., a dialog) when something potentially interesting happens, like the user clicks on them.
In particular, a button control sends its parent a BN_CLICKED notification through the WM_COMMAND message. By handling the WM_COMMAND message in your main window's window procedure (WndProc) method, you can check that the lParam parameter matches your button control's window handle (hWnd) and that the HIWORD(wParam) matches the BN_CLICKED notification code.
You definitely need a good book that contains step-by-step sample code for that one. It's a bit too difficult to explain thoroughly in a Stack Overflow answer.
Writing a GUI application using just the Win32 API is somewhat fun, but also tedious. It is much easier to use a framework of some sort. This doesn't mean it's impossible though. Here's a quick overview of how you do it.
First, you replace the main routine with WinMain. This routine is the new entry point of your application. It will be responsible for creating the windows and setting up a message dispatch loop.
Notice that I said "windows" and not just a "window". In WinAPI, every "control" you see on the "form" is a "window". The "form" itself is a window also. Every window has a window handle (HWND). You can make an application window using CreateWindow. This gets you a window handle that you can pass to the CreateChildWindows function that the GUI builder made for you. This will add child windows (the controls) to the application window.
Now you need to program all these windows. You do that by processing messages. When you create your application window, you need to supply a window procedure. This procedure will respond to messages as they come in. For example, a button click results in a WM_COMMAND message that you will have to handle. The last thing WinMain does is start a message processing loop that repeatedly calls your WndProc for any incoming message.
This will all start to make sense once you work through the tutorial linked in the other answer. Then you will probably get tired of this and pick up a GUI toolkit :)

Custom Find/Replace dialog box

First of all, please bear in mind that I'm new to Windows Programming. I'll try to cover my question in great detail, so that hopefully the answer will be too.
A short introduction:
I'm copying writing a Notepad-like application using Win32 API and pure C. For those of you familiar with Petzold's Windows Programming, this is a modified version of his POPPAD program which he used to describe Common Dialog Boxes. I'm writing this strictly for educational purposes, so please refrain from posting comments like "why you using old technology, use .NET", as those comments will not help me solve my problem :).
Description of a problem:
Petzold in his POPPAD program used Common Dialog Boxes to write this Notepad-like application. He used Edit Control to provide all the functions of a basic text editor. POPPAD, much like a Notepad, also had Find and Replace dialog boxes where you could, well, find stuff AND replace it! Mind boggling, I know.
So this is where I wanted to test my newly acquired knowledge from reading the past chapters, as I decided to write my very own Find and Replace dialog box. Granted, it would be in the simplest form possibly. How hard can it be? You have one text field where you enter some text and you have one fancy button which says "Find!" on it.
Now I'd like to remind you once more that I'm new to Windows programming, so excuse me for any possibly newbie questions. Also, I'd like to point out that I'll focus solely on making the Find dialog box working, as Replace shouldn't be too hard to implement then.
So I played with the resource editor in Visual Studio, and few hours later I got this:
(stackoverflow doesn't actually allows me to post images, so here's the link below)
http://i.imgur.com/R98x4.png
I named this dialog box "Find" (with the quotation marks), so I don't have to use MAKEINTRESOURCE macro in my program, as per Petzold's school of thought. I changed the caption of "Ok" button to "Find Next" and changed it's ID from IDOK to IDC_FIND. Also changed IDCANCEL to IDC_CANCEL and that single line Edit Control is IDC_FIND_FIND.
Now to the more serious things. In my main program's Windows Procedure, I have this piece of code:
case IDM_SEARCH_FIND:
hDlgModeless = CreateDialog (hInst, TEXT ("Find"),
hwnd, FindDlgProc) ;
return 0 ;
IDM_SEARCH_FIND is a message identifier of a Menu item, which when clicked should open up the Find dialog box. CreateDialog function is used to create a modeless dialog box and store it's handle into a global variable hDlgModeless. FindDlgProc is name of the dialog box procedure where (I think) all the code of finding the text should go.
So without further ado, here's the code of my Find dialog box procedure:
BOOL CALLBACK FindDlgProc (HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
static TCHAR szFindWhat[MAX_STRING_LEN]; //Text to find
static int iOffset ; //Offset from the beginning of Edit control to the result
int iLength, iPos, iSingleLength ; //Length of a main Edit control and single line Edit control
PTSTR pstrDoc, pstrPos ;
switch (message)
{
case WM_INITDIALOG:
return TRUE ;
case WM_COMMAND:
switch (LOWORD (wParam))
{
//If the button "Find Next" has been pressed, process all the logic of finding the text
case IDC_FIND:
// Get the text from a single-line edit control in Find dialog box
// and save it in szFindWhat variable
iSingleLength = GetWindowTextLength(GetDlgItem(hDlg, IDE_FIND_FIND)) ;
GetWindowText(GetDlgItem(hDlg, IDE_FIND_FIND), szFindWhat, iSingleLength) ;
// Get the text from a main Edit control, allocate memory for it
// and store it in pstrDoc variable
iLength = GetWindowTextLength (hwndEdit) ;
if (NULL == (pstrDoc = (PTSTR) malloc ((iLength + 1) * sizeof (TCHAR))))
return FALSE ;
GetWindowText (hwndEdit, pstrDoc, iLength + 1) ;
// Search the document for the find string
pstrPos = _tcsstr (pstrDoc + iOffset, szFindWhat) ;
free (pstrDoc) ;
// Return an error code if the string cannot be found
if (pstrPos == NULL)
return FALSE ;
// Find the position in the document and the new start offset
iPos = pstrPos - pstrDoc ;
iOffset = iPos + lstrlen (szFindWhat) ;
// Select the found text
SendMessage (hwndEdit, EM_SETSEL, iPos, iOffset) ;
SendMessage (hwndEdit, EM_SCROLLCARET, 0, 0) ;
case IDC_CANCEL:
DestroyWindow (hDlg) ;
hDlgModeless = NULL ;
break ;
}
break ;
case WM_CLOSE:
DestroyWindow (hDlg) ;
hDlgModeless = NULL ;
break ;
default:
return FALSE;
}
return FALSE ;
}
The only actual error I get here is that hwndEdit is undeclared identifier. hwndEdit is the main Edit control (not the single-line in Find dialog box). How do I get the handle to hwndEdit while I'm in a Find dialog box procedure?
I'd like to point out that I'm feeling a bit over my head here, so please say if I'm missing/doing wrong something obvious. I'm pretty sure that even if I fix the only error I'm getting, the program still won't work. Even though the concept of what I should be doing sounds fairly simple, actually programming that seems quite difficult :)
This is what the code above should do, in simplest form:
- Get the text from Find dialog box which I wish to search
- Get the text from main Edit control
- Do a substring search from the last offset (don't start from beginning every time)
- Find the position of a result and readjust offset
- Select the found text
I know I haven't really asked a direct question here, well I guess the direct question would be: How do I make this work? :) But more importantly it would be to understand how this exactly works. I'd appreciate if you can provide me with an elaborate answer. Thanks for all the help!
It looks like you're very close, you just need to get the hwndEdit from your main window. You passed your main window's handle in as a parent to your dialog box, so you should be able to get the parent window of your dialog box like so:
HWND hwndParent = GetParent(hDlg);
After that you can get the edit control from that parent by referencing the edit control ID in your main window definition. Something like this (assuming the control ID is IDC_EDIT):
HWND hwndEdit = GetDlgItem(hwndParent, IDC_EDIT);

ShowWindow within WM_CREATE

The way I see it, one use of a Window Procedure's WM_CREATE message is to relieve the caller of the burden of executing static code at window initialization. My window is to execute some code in the WM_CREATE message, including the ShowWindow function. I also want the ShowWindow to behave properly according to the nCmdShow parameter in WinMain. So here is pseudo-code to show how I have things set up:
int g_nCmdShow;
WinMain(..., int nCmdShow)
{
g_nCmdShow = nCmdShow;
...
CreateWindow(..., WM_OVERLAPPEDWINDOW, ...)
...
}
WndProc()
{
...
WM_CREATE:
...
ShowWindow(hWnd, g_nCmdShow);
...
...
}
So I set up the program to run Minimized (using Windows XP I created a shortcut to the .exe, and set up the properties of it accordingly), and it displays on the taskbar minimized but it does not restore when I click on it. Likewise, if I run it Maximized, it does not behave correctly when I click the maximize button (to un-maximize it).
What is the correct way to use nCmdShow-compatible ShowWindow within the WM_CREATE message?
The problem is that the window's restore bounds get affected by this. They become the size of the window after WM_CREATE returns. You would have to modify your code to re-establish those restore bounds:
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 300, 200, NULL, NULL, hInstance, NULL);
WINDOWPLACEMENT wp;
GetWindowPlacement(hWnd, &wp); // <= Note wp.rcNormalPosition after this call!
RECT rc = {100, 100, 400, 300};
wp.rcNormalPosition = rc;
SetWindowPlacement(hWnd, &wp);
You're not ahead by doing it this way.
If you absolutely have to keep it in the WndProc, try
case WM_CREATE:
PostMessage(hwnd,WM_APP,0,0);
break;
case WM_APP:
ShowWindow(hwnd,SW_SHOW);
break;
But if this is so important, why not just have a helper function that creates the window and calls ShowWindow? MyWindowType_Create(...) etc
Having the window show itself, or set its own position, is a bad design choice that goes against how WinAPI was meant to be used. The right place to do these decisions is in the code that creates the window. It's already reflected in the fact that the CreateWindow is responsible for the initial window placement and WS_VISIBLE style.
In your code you should call ShowWindow in WinMain, which will also eliminate the need for the g_nCmdShow global:
WinMain(..., int nCmdShow)
{
...
hWnd = CreateWindow(..., WM_OVERLAPPEDWINDOW, ...)
ShowWindow(hWnd, nCmdShow);
...
}
WndProc()
{
...
WM_CREATE:
...
...
}
WM_CREATE is rather responsible for initializing window-class specific behavior. Creating child windows or initializing internal data structures and the cbWndExtra slots are examples of that (e.g. think of implementing a list-box).
Can you handle WM_WINDOWPOSCHANGED and override the window size the first time the window is restored? Use GetWindowPlacement to find out if the window got restored.

Resources