Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Filling the blanks

visual c en


Filling the blanks

Input goes through dialog boxes under windows. They are ubiquitous; so let's start to fill our skeleton with some flesh. Let's suppose, for the sake of the example that we want to develop a simple text editor. It should read some text, draw it in the screen, and provide some utilities like search/replace, etc.

First, we edit our menu, and add an "edit 525b17f " item. We open the directory window, and select the menu:



We arrive at the menu editor . If we open each branch of the tree in its left side, it looks like this:

We have at the left side the tree representing our menu. Each submenu is a branch, and the items in the branch; the leaves are the items of the submenu. We select the "File" submenu and press the "insert" key. We obtain a display like this:

A new item is inserted after the currently selected one. The name is "Popup", and the first item is "New item". We can edit those texts in the window at the right: We can change the symbolic name, and set/unset several options. When we are finished, we press "Apply" to write our changes to the resource.

OK, we change the default names to the traditional "Edit" and "Search", to obtain this display:

We will name the new item IDM_SEARCH. I am used to name all those constants starting with IDM_ from ID Menu, to separate them in my mind from IDD_ (ID Dialog).

We can now start drawing the "Search" dialog. Just a simple one: a text to search, and some buttons to indicating case sensitivity, etc. We close the menu editor, and we start a new dialog. In the "Resources" submenu, we find a "New" item, with several options in it. We choose the "dialog" option.

The dialog editor builds an empty dialog and we are shown the following parameters dialog:

Even if this quite overwhelming, we are only interested in two things: the title of the dialog and the symbolic identifier. We leave all other things in their default state. We name the dialog IDD_SEARCH, and we give it the title "Text search". After editing it looks like this:

We press the OK button, and we do what we did with the dialog in the DLL, our first example. The finished dialog should look roughly like this:

An edit field, and two push button for OK and Cancel. The edit field should receive the ID IDTEXT.

Now comes the interesting part. How we connect all this?

We have to first handle the WM_COMMAND message, so that our main window handles the menu message when this menu item is pressed. We go to our window procedure MainWndProc. Here it is:

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)

return 0;

We can see that it handles already quite a few messages. In order,

We see that when the main window is resized, it resizes its status bar automatically.

When the user is going through the items of our menu, this window receives the WM_MENUSELECT message from the system. We show the appropriate text with the explanations of the actions the menu item in the status bar.

When a command (from the menu or from a child window) is received, the parameters are passed to a macro defined in windowsx.h that breaks up the wParam and lParam parameters into their respective parts, and passes those to the MainWndProc_OnCommand function.

When this window is destroyed, we post the quit message.

The function for handling the commands looks like this:

void MainWndProc_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)

We find a comment as to where we should add our new command. We gave our menu item "Search" the symbolic ID of IDM_SEARCH. We modify this procedure like this:

void MainWndProc_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)

break;

case IDM_EXIT:

PostMessage(hwnd, WM_CLOSE,0,0);

break;

}

When we receive the menu message then, we call our dialog. Since probably we will make several dialogs in our text editor, it is better to encapsulate the difficulties of calling it within an own procedure: CallDialog. This procedure receives the numeric identifier of the dialog resource, the function that will handle the messages for the dialog, and an extra parameter for the dialog, where it should put the results. We assume that the dialog will return TRUE if the user pressed OK, FALSE if the user pressed the Cancel button.

If the user pressed OK, we search the text within the text that the editor has loaded in the function DoSearch.

How will our function CallDialog look like?

Here it is:

int CallDialog(int id,DLGPROC proc,LPARAM parameter)

We could have returned the value of the DialogBoxParam API immediately but I like storing function return values in local variables. You never know what can happen, and those values are easily read in the debugger.

We have to write a dialog function, much like the one we wrote for our string DLL above. We write a rough skeleton, and leave the details for later:

BOOL CALLBACK SearchDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

return FALSE;

This does nothing, it doesn't even put the text in the received parameter, but what we are interested in here, is to first ensure the dialog box shows itself. Later we will refine it. I develop software like this, as you may have noticed: I try to get a working model first, a first approximation. Then I add more things to the basic design. Here we aren't so concerned about design anyway, since all this procedures are very similar to each other.

The other procedure that we need, DoSearchText, is handled similarly:

int DoSearchText(char *txt)

We just show the text to search. Not very interesting but.

We compile, link, the main application window appears, we select the "Search" menu, and. we see:

What's wrong?????

Well, we have inverted the parameters to the MessageBox procedure, but that's surely not the point. Why is the dammed dialog box not showing?

Well, here we need a debugger. We need to know what is happening when we call the dialog box. We press F5, and we start a debugging session. The debugger stops at WinMain.

Now, wait a minute, our window procedure that receives the message from the system is called indirectly from Windows, we can't just follow the program blindly. If we did that, we would end up in the main loop, wasting our time.

No, we have to set a breakpoint there. We set a breakpoint when we call the dialog using the F2 accelerator. We see that Wedit sets a sign at the left to indicate us that there is a breakpoint there. Then we press F5 again to start running the program.

Our program starts running, we go to the menu, select the search item, and Wedit springs into view. We hit the breakpoint. Well that means at least that we have correctly done things until here: the message is being received. We enter into the CallDialog procedure using the F8 accelerator. We step, and after going through the DialogBoxParam procedure we see no dialog and the return result is -1. The debugger display looks like this:

We see the current line highlighted in yellow, and in the lower part we see the values of some variables. Some are relevant some are not. Luckily the debugger picks up r as the first one. Its value is -1.

Why -1?

A quick look at the doc of DialogBoxParam tells us "If the function fails, the return value is -1."

Ahh, how clear. Yes of course, it failed. But why?

Mystery. There are no error codes other than just general failure. What could be wrong?

Normally, this -1 means that the resource indicated by the integer code could not be found. I have learned that the hard way, and I am writing this tutorial for you so that you learn it the easy way. The most common cause of this is that you forgot to correctly give a symbolic name to your dialog.

We close the debugger, and return to the resource editor. There we open the dialog box properties dialog box (by double clicking in the dialog box title bar) and we see. that we forgot to change the name of the dialog to IDM_SEARCH!!! We correct that and we try again.

OK, this looks better. The dialog is showing.

The rest is quite trivial most of the wok was done when building the DLL. Actually, the dialog box is exactly the same.



The resource editor has several editors specialized for each kind of resource. You get a dialog box editor, a menu editor, a string table editor, an accelerators editor, and an image editor. Each one is called automatically when clicking in a resource from the menu, obtained with the dir button.

This type of interface requires an action from the part of the user to indicate when it is finished modifying the name and desires to "apply" the changes. Another possibility would be that the resource editor applies the changes letter by letter as the user types them in, as some other editors do. This has the advantage of being simpler to use, but the disadvantage of being harder to program and debug. As always, an the appearance of the user interface is not only dictated by the user comfort, but also by the programming effort necessary to implement it. You will see this shortly when you are faced with similar decisions.

A debugger is a program that starts another program, the "program to be debugged" or "debuggee", and can execute it under the control of the user, that directs the controlled execution. All C development systems offer some debugger, and lcc-win32 is no exception. The debugger is described in more detail in the user's manual, and it will not be described here. Suffice to note that you start it with F5 (or Debugger in the compiler menu), you can single step at the same level with F4 and trace with F8. The debugger shows you in yellow the line the program will execute next, and marks breakpoints with a special symbol at the left. Other debuggers may differ from this of course, but the basic operations of all of them are quite similar. Note that lcc-win32 is binary compatible with the debugger of Microsoft: you can debug your programs using that debugger too.

To be able to use the debugger you need to compile with the g2 flag on. That flag is normally set by default. It directs the compiler to generate information for the debugger, to enable it to show source lines and variable values. The compiler generates a whole description of each module and the structures it uses called "debug information". This information is processed by the linker and written to the executable file. If you turn the debugging flag off the debugger will not work. The best approach is to leave this flag on at all times. Obviously the executable size will be bigger, since the information uses up space on disk. If you do not want it, you can instruct the linker to ignore it at link time. In this way, just switching that linker flag on again will allow you to debug the program.

The debug information generated by lcc-win32 uses the NB09 standard as published by Microsoft and Intel. This means that the programs compiled with lcc-win32 can be debugged using another debugger that understands how to use this standard.

Why didn't we use the DLL to ask for the string to search? Mostly because I wanted to give you an overview of the whole process. A good exercise would be to change the program to use the DLL. Which changes would be necessary? How would you link?


Document Info


Accesari: 966
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )