This review-console application and long text name include console applications in this chapter. It looks like a DOS application, but it can access the 4GB address space provided by Win32. In this chapter, you will also see how to use long file names and Win32 file I / O and other introductions. All programs in this chapter are specifically for Windows NT and Windows 9x, they cannot run on 16-bit mode and Windows 3.x. This chapter also includes the following: • For the process of designing the event program from the beginning to the end, it is an outline, especially if you have the opportunity to build your own event cycle. · Use the mouse as input in the console application. · Low-level console I / O routine. · Call the GUI routine in the console application. If you need to get a file name or to perform some operations processed by Windows interface, it is very useful to call the GUI. · Get and use long file names in GUI and console applications. • Use the FindFirstFile and the FindNextFile function in the directory to repeatedly scan the director file name. · Create a console window in the GUI application, which is very useful for debugging. 8.1 Console application Most people think of Windows 9X, the first thing I think in the brain is GUI. Windows 9x seems to be more graphic than Windows 3.x, with more graphical elements, users dependher more dependent to deal with the system. However, when you know that Windows 9x is fully supported by text mode, it may be somewhat strange. You can build 32-bit Windows 9x applications that fully use the Win32 API, but it runs in text mode. You can start them at the command prompt, and they never leave the command prompt. In other words, it doesn't have to pop up a window. Here I am talking about "Don't do it" means that if they need windows, they can also pop up the window. In fact, there is an example in this chapter to explain how to pop up a public dialog in a console application (this is not a necessary recommendation, but this is achievable). Program List 8.1 lists the Emily program, which is the first program in several console applications described in this chapter.
Listing 8.1 Emily application is a Win32 console application
///
// emily.cpp
// Copyleft (c) 1999 Skyline
// Demostrate Simple Console Application
///
#include & ltwindows.h>
#include & ltstdio.h>
#include & ltconio.h>
/
// Program Entry Point
/
Int main (void)
{
Printf ("/ N / Nthe Soul Selects Her Own Society, / N");
Printf ("Then Shuts the Door; / N");
Printf ("On Her Devine Majority / N");
Printf ("obtrude no more./n");
Printf ("unmoved, she notes the chariot's pausing / n");
Printf ("at her lo gate; / n");
Printf ("unmoved, an emperor is kneeling / n");
Printf ("UPON HER MAT./N");
Printf ("I'VE KNOWN HER from an ample nation / n");
Printf ("Choose One; / N"); Printf ("Then Close The Valves of Her Ayyention / N");
Printf ("Like Stone / N");
Printf ("/ N-Emily Dickinson / N");
Printf ("/ n / npress any key to pay ... / n");
_Getch ();
Return 0;
}
When this program runs, the following poems are output in the text mode:
The Soul Selects Her Own Society,
Then Shuts the door;
On Her Devine Majority
Obtrude no more.
Unmoved, She Notes The Chariot's Pausing
At her low gate;
Unmoved, an emperor is kneeling
Upon Her Mat.
I'VE KNOWN HER from an AMPLE NATION
Choose one;
Then Close The Valves of Her Ayyention
Like stone
-Emily dickinson
If you use Microsoft's compiler, you can follow the steps: Select New Project, then set the Project Name to Emily, set the Project Type to Win32 Console Application. Insert the C source file in the Project, and finalize your program code into the original file, compile and run it. After the Emily program is simplified, the most basic explanation will explain the content, and then the following code is left:
#include & ltstdio.h>
Int main (void)
{
Printf ("/ N / Nthe Soul Selects Her Own Society, / N");
Return 0;
}
Isn't this a programmer's dream? Here, everything I have to do is pointed out that it is just a traditional DOS application. This program takes advantage of Windows.h files. The point of the content described above is that the encoding of the console can be the same as the DOS application, as long as you are listed in the file you want to include. 8.2 Constructing a 4GB array If you have done a time program design, you are likely to encounter 64KB restrictions, this restriction is for 16-bit applications, because you can only use 16 bits, you can't represent a number greater than 64KB . Even in Windows 3.x, this annoyed 64KB still limits us. Although this environment allows us to get rid of 640kb size limit, we still feel very troublesome, there are data segments, stacks and piles. However, the console application is not limited by the 64KB boundary, as long as you need, you can assign a huge memory block. Of course, no one can have the entire 4GB of memory in the 32-bit system to address. Even if there is a 4GB of memory, they cannot really build a 4GB array. Because there are almost half space in 4GB belong to the system. In any case, Win32 program makes us very free and open compared to the old 16th world. Perhaps the most benefit from this new liberal kingdom is mathematician and graphic programmers. Programmers that need to construct a large number are no longer limited by 64kb. Of course, everyone is beneficial to varying degrees. At least this means that large data blocks can reside in the data segment without having to put them in the heap. The advantages of 4GB have been said enough, now let's take a look at what is the feeling like a large number, it is not got with some kind of means, it is a real thing - large groups in a uniform memory space Expand. Now let's take a look at the large group of procedures 8.2. Program List 8.2 BigArray Program
///
// BigArray.cpp
// Copyleft (c) 1999 Skyline
// Demostrate Simple Console Application
///
#include & ltwindows.h>
#include & ltstdio.h>
#include & ltconio.h>
#define maxX 20
#define maxy 2000
/
// Program Entry Point
/
Int main (void)
{
INT I, J;
INT BIGONE [MAXX] [MAXY];
Printf ("/ N / NThe Size of the Array IS% D Bytes.", Sizeof (BIGONE));
Printf ("/ n / npress any key to pay ... / n");
_Getch ();
For (j = 0; j & ltmaxy; j )
For (i = 0; I & ltmaxx; i )
BIGONE [I] [J] = i;
For (j = 0; j & ltmaxy; j )
{
Printf ("Row:% D Data =>", J);
For (i = 0; I & ltmaxx; i )
Printf ("% D", bigone [i] [j]);
Printf ("/ n");
}
Printf ("/ n / npress any key to pay ... / n");
_Getch ();
Return 0;
}
When you run the BigArray program, you will first get a report of an array size. In this case, the body on the screen shows that the size of this array is 160,000 bytes. When you press any key, the entire array situation will scroll through the screen. However, in this way, you have no practical use from everything you happen to what happened. This is just to make you feel the entire 32-bit address space. Needless to say, you can build a large number of more than 160,000 bytes. The reason why I make this array relatively small because I want to print all the contents of the array on the screen. Here I think I should point out that I got the size of the array through the SIZEOF operator: Printf ("/ n / nthe size of the array is% D Bytes.", Sizeof (BIGONE)); you have seen this section The Windows 9x has broken through the old 64KB restrictions, which has made many programmers with Intel chip computers. But Windows 9x's storage mode is not as simple as initially sound. When I know that my program is usually loaded into the 4MB address of the memory (it is 0x00400000 in the hexadecimal), I am very strange. When you first consider this problem, you will feel that the program is not imagined. Moreover, your program is loaded by the location of the Hinstance for your application. If you continue and run the program, and put Hinstance into the debugger's monitor window, the number you see is your program being loaded to the address of the virtual storage. 8.3 Construction Console Application As you can see, many of the basic actions of screen I / O can only work normally in console mode. That is, in the console application, you must include stdio.h and / or conio.h files to use printf, gets, getchar, getch and other functions. These functions allow you to control the output data on the screen. However, you should also understand several console functions in Win32. For example, you can get a handle of standard input and standard output, and then use the Win32 itself command to output with the specified foreground color and background colors with the specified position of the screen with the specified position of the screen. In the Mouse program previously introduced, you have seen you can also know that the mouse button action and the user's hit button on the keyboard. Similarly, these controls can be obtained from the runtuus from C, but I hope to explain how to use the Windows itself to achieve the same purpose, so you can understand the actual situation in the console. I will let you watch a FAITH program. In addition to the final use of the Getch routine in the program, this code does not use other standard library functions in the C language, all of which is implemented by the Win32 itself. Program List 8.3 Faith Program
///
// Faith.cpp
// Copyleft (c) 1999 Skyline
// Demostrate Simple Console Application
///
#include & ltwindows.h>
#include & ltstdio.h>
#include & ltconio.h>
#define alt1 foreground_blue | Foreground_green
Void CLRSCR ();
Void Writexy (int X, int y, lpstr s, word attr);
Handle Hout;
/
// Program Entry Point
/
Int main (void)
{
SetConsoleti ("Skyline Console"); hout = getstdhandle (std_output_handle);
CLRSCR ();
Writexy (0, 1, "faith is a fine invention.", Alt1);
Writexy (0, 2, "for Gentlemen Who See;", Alt1);
Writexy (0, 3, "But MicroScopes Are Prudent", Alt1);
Writexy (0,4, "in an energency!", Alt1);
_Getch ();
Return 0;
}
Void CLRSCR ()
{
DWord Numwritten;
Coord C;
C.x = 0;
C.y = 0;
FillconsoleOutputCharacter (Hout, '', 80 * 25, C, & Numwritten);
}
Void Writexy (int X, int y, lpstr s, word attr)
{
Coord C;
DWORD RESULT;
C.x = x;
C.Y = Y;
SetConsoleTextAttribute (hout, alt1);
SetConsolecursorPosition (HOUT, C);
Writeconsole (HOUT, S, STRLEN (S), & Result, NULL);
}
There is no two lines of code in the above program, but you can add them to the program, used to assign its own console: freeconsole (); so, the program is released with the first call release the current console Ended its command dialogue. Then allocate a new console with the second call, enable it its own window. In most cases, you can do this, this will only make the user confused. If you want to start a console within a standard Windows program, call the allocconsole function is usually useful. In order to set a title to the console, the following API function is used in the Faith program: setConsoletE ("skyline console"); if the program is running as a sub-window for the Windows desktop, this title will appear, but it does not appear in the console. Some places in the title bar provided by Windows GUI. The next step is to obtain the output handle, the program outputs the output location represented by the handle: hout = getstdhandle (std_output_handle); Hout Description is the Handle Type. If you have to get a handle, you can use the following line of code: hout = getstdhandle; the Faith program wishes to get control over the entire screen. That is, it can move the cursor at will on the screen, so it is to be set to blank:
Void CLRSCR ()
{
DWord Numwritten;
Coord C;
C.x = 0;
C.y = 0;
FillconsoleOutputCharacter (Hout, '', 80 * 25, C, & Numwritten);
}
This routine has the same function as the CLRSCR you see in many C runners. FillconsoleOutputCharacter Syntax: The FillConsoleoutPutcharacter function is defined as follows: Bool FillConsoleoutputCharacter
Handle hconsoleoutput,
Char ccharacter,
DWORD NLENGTH,
Coord dwwritecoord,
LPDWORD LPNUMBEROFCHARSWRITEN
);
The FillConsoleOutputCharacter function uses the standard output handle as the first parameter, and the characters to be output are placed in the second parameter. The number of output characters is placed in the third parameter. The last parameter is used to store the number of bytes written and the return value of the function. If you write the characters exceeded one line, the output will go to the next line to continue. If you try to write the number of characters exceeds the buffer range, what does not happen, nor does it have additional calls to handle these more characters. This way, if you use the code writer with 80x25 format. If you want to calculate the exact number to refresh the entire screen character, you can use the getConsolescreenBufferInfo function. You should notice that there is a FillConsoleoutPutAttribute routine that will be described later in this chapter. It allows you to set foregrounds and background colors for screen locations, just like FillConsoleOutputCharacter to let you display characters in a specified area of the screen. Here is an example: FillConsoleOutputCharacter (hout, '', 80 * 25, c, "); if you want to output your text on the screen, you can use WriteConsole, SetConsoleTextTribute and SetConsolecursorPosition functions:
Void Writexy (int X, int y, lpstr s, word attr)
{
Coord C;
DWORD RESULT;
C.x = x;
C.Y = Y;
SetConsoleTextAttribute (hout, alt1);
SetConsolecursorPosition (HOUT, C);
Writeconsole (HOUT, S, STRLEN (S), & Result, NULL);
}
In this routine, I use three functions to complete the task of using a set of specific colors on the screen, and you can use the WriteConsole function to do only with the WriteConsole function. SetConsoleTextAttribute uses the standard output handle as the first parameter. The second parameter is attribute, and the property can consist of one or more of the following values: Foreground_Blue, Foreground_Green, Foreground_red, Foreground_INTENSITY, Background_Blue, Background_Green, Background_red, and Background_INTENSITY. Different effects can be produced in different combinations of these values. SetConsolecursorPosition function relies on the following data structure: typedef struct_coord {short x; short y;} coord; You can pass this structure to the second parameter of the SetConsolecursorPosition function, the handle of the console buffer as the first parameter. Below is a description of the WRITECONSOLE routine, which is the Win32 itself routine, which can be used instead of the PUTS function. WriteConsole Syntax: The following is an explanation of the WriteConsole function:
Bool writeconsole
Handle hconsoleoutput,
Const void * lpbuffer, DWORD NNUMBEROFCHARSTOWRITE,
LPDWORD LPNUMBEROFCHARSWRITEN,
LPVOID LPRESERVED
);
The WRITECONSOLE function is used to write a string to the screen. The first parameter passed to it is the handle of the console screen buffer; the string is the second parameter; the number of characters to be written as the third parameter. The address returned by the number of written characters is placed in the fourth parameter, and the last parameter is retained to Windows or thereon. Here is an example: Writeconsole (HOUT, "Hello", 5, & Result, NULL); I want to point out again, here I just make a simple introduction to the console application, if you need to learn more about this problem, you can open WinCon.h file is read. 8.4 Handling Mouse and Keyboard This section will introduce the Mouse program that allows you to explain how to handle your mouse and keyboard in your console application. This is a simple program that reports the current position of the mouse, the current state of the mouse button and any alphanumeric key pressed by the user. I would like to emphasize that most of the I / O operations in C's standard libraries can also do these things very well in constructor applications based on command behavior. For example, you can call the Gets function to process the user's body input. But if you want to track your mouse, you must of course use the internal routine of the console. Not only that, if you start a console window from a GUI application, there is a problem with some standard I / O library routines. If you want to run a console in the GUI application, you should use the few Win32 itself introduced here. The program-oriented programming is discussed in the previous section of this chapter. The program here is an example of how to create an event program from the beginning. That is, this code illustrates how the event Windows routine is actually working. If you haven't seen such a code before, it can help you because it gives some prompts for how to construct a message-oriented operating system. Let us now prepare the mouse program and run it. Program List 8.4 is its source code. The following sections will discuss this simple application's key points.
Program List 8.4 Mouse program Description How to use a mouse in a console application?
///
// mouse.cpp
// Copyleft (c) 1999 Skyline
// Demostrate Simple Console Application
///
#include & ltwindows.h>
#include & ltstdio.h>
Void gotoxy (short x, short y);
Void Blankline (Short Y);
Void CLRSCR ();
Void Write (LPSTR S);
Void Handlemouse;
Void HandleKey (Key_Event_Record Key);
Void sygoodbye ();
HANDLE HOUT, HIN;
/
// Program Entry Point
/
Int main (void)
{
SetConsoleti ("Skyline Console");
DWORD RESULT;
INPUT_RECORD BUF;
Hout = getstdhandle (std_output_handle);
Hin = getstdhandle (std_input_handle);
CLRSCR ();
Gotoxy (0,24);
Write ("Move Mouse, Press Keys, Double Click to EXIT ...");
DO
{
Readconsoleinput (HIN, & BUF, 1, & Result); if (buf.eventtype == mouse_event)
HandleMouse (buf.event.mouseevent);
IF (buf.eventtype == key_event)
HandleKey (buf.event.keyevent);
} while (! (buf.eventtype == mouse_event &&
BUF.Event.mouseevent.dweventflags == double_click);
Saygoodbye ();
Return 0;
}
//
// gotoxy Move Cursor To Col, Row
//
Void gotoxy (Short X, Short Y)
{
Coord C;
C.x = x;
C.Y = Y;
SetConsolecursorPosition (HOUT, C);
}
//
// Blank a line of text at position y
//
Void Blankline (Short Y)
{
DWord Numwritten;
Coord C;
C.x = 0;
C.Y = Y;
FillconsoleOutputCharacter (Hout, '', 80, C, & Numwritten;
}
//
// clear the screen
//
Void CLRSCR ()
{
Short I;
For (i = 0; i <25; i ) Blankline (i); gotoxy (0,0);} ///write a line of text // void write (lpstr s) {dWord Result; WriteConsole (HOUT, S, Strlen (s), & result, null;} /// Report on position of mouse // void handlemouse (mouse_event_record mouse) {char s [150]; sprintf (s, "buttons:% lu, x:% 2lu Y:% 2lu / N ", mouse.dwbuttonState, mouse.dwmouseposition.x, mouse.dwmouseposition.y); gotoxy (0, 0); Write (s);} /// Report on key strokes entered //// Void HandleKey (key_event_record key) {char s [S, "You Pressed:% C", key.uchar); gotoxy (0, 1); Write (s); sprintf (s, "Virtual Key: % 3D ", Key.WVirtualKeycode; gotoxy (0, 2); Write (s);} /////////////////////////////////////////////00- CLRSCR (); Printf ("Enter Your Name:"); Gets (S); Printf ("/ ngoodbye% s! / N", s);}
This program only uses the current location of the mouse and reports the user's button action. Its core code is the following event loop: DO
{
ReadconsoleInput (Hin, & Buf, 1, & Result);
IF (buf.eventtype == mouse_event)
HandleMouse (buf.event.mouseevent); if (buf.eventtype == key_event)
HandleKey (buf.event.keyevent);
} while (! (buf.eventtype == mouse_event &&
BUF.Event.mouseevent.dweventflags == double_click);
This code repeatedly runs until the user doubles the screen with the mouse. Use the READCONSOLEINPUT routine to check the user's input every time the cycle begins. Syntax: ReadconsoleInput Bool Readconsoleinput
Handle HconsoleInput,
PINPUT_RECORD LPBUFFER,
DWORD NLENGTH,
LPDWORD LPNUMBEROFEVENTSREAD
);
Many parameters of this routine are the same as those discussed in the previous chapter, so this is not necessary to repeat them again. The new information in the READCONSOLEINPUT routine is the buffer of the input_record type:
Typedef struct _input_record {
Word evenettype;
Union {
Key_Event_Record KeyEvent;
Mouse_Event_Record MouseEvent;
Window_buffer_size_record windowbuffersizeEvent;
Menu_event_record menuevent;
Focus_Event_Record Focusevent;
} Event;
INPUT_RECORD;
This record contains tracking information for keyboard events, mouse events, buffers size, menu events, and current focus events. For example, when the user moves the mouse or do some input with the keyboard, the results of these actions will be recorded in this structure. Below I will discuss mouse_event_recond and key_event_recond, if you are interested in other structures, please refer to online help information. The EventType field will be discussed later. The basic idea you have to master for the ReadConsoleInput routine is: it allows the system to fill the program's current status information into the Input_Record structure. This routine does not wait for user input information, it just checks what happens now, if there is nothing, it will return and report the situation. Below is an example of using this function: ReadConsoleInput (HIN, & BUF, 1, & RESULT); you should take some time carefully to detect this event loop and understand how the ReadConsoleInput function is with this loop. The key is that you have to understand that a place in Windows internal underlying, there is also a loop similar to this loop is performing, and all event-oriented programs are organized in this way. After calling the ReadConsloeInput function, the next step is to check if there is a certain important event already. For example, if you want to know if there is a mouse event or no one button on the keyboard is pressed. Check for these events is implemented by viewing the EventType field in the input_record record: if (buf.eventtype == mouse_event)
HandleMouse (buf.event.mouseevent);
IF (buf.eventtype == key_event)
HandleKey (buf.event.keyevent);
If a mouse event appears, call the following routines:
Void Handlemouse (Mouse_Event_Record Mouse)
{
Char S [150]; Sprintf (s, "buttons:% lu, x:% 2lu Y:% 2lu / N",
Mouse.dwbuttonState,
Mouse.dwmouseposition.x,
Mouse.dwmouseposition.y);
Gotoxy (0,0);
Write (s);
}
Record of the mouse event is: type_event_record {
Coord dwmouseposition;
DWORD DWBUTTONSTATE;
DWORD DWCONTROLKEYSTATE;
DWORD DWEVENTFLAGS;
} Mouse_event_record;
The key field here is the first two. The current mouse position is placed in the first field, and the mouse button is recorded in the second field. In most cases, you can assume that the button is set to 1 when the left mouse button is set, and the second button is set to 2 in the mouse. However, if you want to read out information about the mouse status field, you need to perform some of the events. That is, each mouse button is represented by one of this 32-bit field. This also means that the routine can process imaginable devices, which can have more than two or three buttons. You can learn about the interpretation by online help. The third field dwcontrolKeyState is used to record if there is a special key being pressed. For example, it can be used to track Ctrl keys, ALT keys, and Shift keys. The last field records if there is a double-click mouse event or whether the mouse is simply moved. To help read, define the following value: mouse_moved double_click Click the button with 0. Understanding this record, you can understand how the HandleMouse function is working. This function is just a simple report of this status of the previous two fields, and writes their value on the top of the screen. The code around the HandleMouse routine is the main part of the event program. In the main execution time of the mouse program, the cycle is performed over a very fast speed. The corresponding routine is called for each check in the cycle to occur. In the example here, these routines are only outputted on the screen on the screen, and there is no thing to send anything in Windows, but pack the message and send it out. Your program captures WM_MOUSEMOVE, WM_KEYDOWN, WM_LBUTTONDOWN, and other messages and responds. When you understand these, you will feel very simple. Processing the keyboard input event is simpler than the processing mouse input: Void HandleKey (key_event_record key)
{
Char s [100];
Sprintf (s, "you press:% c", key.uchar);
Gotoxy (0,1);
Write (s);
Sprintf (S, "Virtual Key: 3D", Key.WVirtualKeycode;
Gotoxy (0, 2);
Write (s);
}
The structure of the key_event_record record is as follows: type_event_record {ÄXEY_EVENT_RECORD {
Bool bkeydown;
Word WrepeATCount;
Word wvirtualKeycode;
Word wvirtualscancode;
Union {
Wchar unicidechar;
CHAR ASCIICHAR;
} uchar;
DWORD DWCONTROLKEYSTATE;
KEY_EVENT_RECORD;
The most important fields are WvirtualKeyCode and Uchar. The encoding of the virtual key has been introduced earlier and listed under the Title of the online help Virtual Key Codes. It helps you track information related to special keys. These special keys have Enter, function keys (F1, F2), and digital keys on the keypad, and the like. As long as it is possible, the code of these special keys can be converted into standard ASCII characters and placed in the UCHAR field. That is to say, if this key is the alphanumeric value or the first half of the ASCII character set, put it into the Uchar field. For example, for the A key, the value of the WVIRTUALKEYCODE field will be 65, and the characters in the UCHAR field will be A or A, which will depend on the state of the SHIFT key. 8.5 Long file name in front of this chapter I have already introduced how to assign memory by block (CHUNK), the block size can exceed 64KB. Many programmers have been looking forward to this function on the PC for many years. Now, this wish is finally realized. This is true for the case of the long text name. Although the implementation of long file names has been dragged, it finally appeared. You can get this very expected function without any special things. When you start using the relevant functions, many of these functions may have been used for many years, you will find that you can use long file names. In long file names, you don't even need to include a special tag or define some special values. There is a such example below. If you have a 32-bit compiler, there is no warning without any publicity, you will suddenly discover, you can use long file names in the first parameter of the Fopen function. This way you can say goodbye to the following code: fp = fopen ("ll071595.txt", "w "); and welcome the code now: fp = foePn ("love letter to margie dated 07-15-95.txt "," w "); this is a very wonderful improvement, of course, we are happy to come this day. In any case, it is hard to feel the romantic breath with a file name called ll071595.txt. However, you should realize that there are still some restrictions on the details of the long file name. For example, you can't write this: fp = foePn ("Letter to Dad Dated 07/15 / 95.txt", "W "); for this special limit, you should not be strange, because in the path, the slash has already There is a more basic meaning, so it cannot be used as a division of the date. In addition, there are still some actual provisions that can do for long file names. This means you want to remind you of yourself, when you write routines, don't contain invalid characters in the path name. You can refer to the help information obtained by the FileOpen and the FileSave Public dialog box. The new long text name system specifies the file name to use the following characters: standard English letters. Standard number. Scheduling of the three letters of the standard. Its ASCII code greater than 127 (this usage is not recommended). The space character (ASCII value is 20h). You can also use these special characters: $% '_ @! () {} ^ # & " ,; = [] File name can grow up to 256 characters. The path name before the file is up to 246 characters. (This is 256 minus the length of DOS 8.3 name). These are limited to you in the establishment of a very long directory, especially when establishing a nested subdirectory.
In the long file name, you can also identify the letters you use, that is, it can distinguish between uppercase A and lowercase A. But it is not used to distinguish a file and another file. For example, there is a file name called my file.txt, then you want to build a file called My File.txt in the same directory, and the system will regard them as the same file name, and the file established will The previous file is overwritten, but keep the name of the previous file. That is, the content of the file has changed but the file name is also retained as my file.txt. If you go to the command prompt after establishing a long text name, you will see the strange content like this: acreat ~ 1.txt 33 7-15-95 13:23
ANFOPE ~ TXT 721 7-15-95 13:05
Anfope ~ 2.txt 721 7-15-95 13:23
Longname.cpp 3077 7-15-95 13:23
Longname.def 78 7-14-95 12:28
Longname.exe 46340 7-15-95 13:23
Longname.mak 622 7-14-95 12:27
The last four names are fully understood. So what is the top three names? These are the alias for the creation of the long text name, which is to make these long file names can work under the old DOS file system. The pseudonym of the three files can be assumed to be the following three file names: a createfile long name.txt an fopen long name 05-23-95.txt An fopen long name 07-17-95.txt once you accept this basics How to change the name of Windows: a createfile long name.txt: acreat ~ 1.txt Note, the following two long file names until the eighth character or even more than eight characters it's the same. This means that Windows cannot simply truncate the name of the text, this is not good. In order to avoid this inappropriate practice, the system has taken a simple strategy, which is added after the truncated file name, so the first file name is last added 1, the second file name is last added 2, so analogy. Studies the following examples can understand the operating mode of the system. Below is the two long file names: An Fopen Long Name 05-23-95.txt An Fopen Long Name 07-17-95.txt The corresponding truncated file name: anfope ~ 1.txt 721 7-15- 95 13:05 Anfope ~ 2.txt 721 7-15-95 13:23 Note that the space in the long file name is removed. Spaces in long file name systems are legal characters, but the DOS file system is processed so good. However, the problem is what you can't guess what kind of short name word will use in the local system that appears in long file name. I know that people hope to develop systems in most situations, but there is no documentation on long file names, and there may be changes in the future system, it is not fixed. However, if you really want to discuss this problem, you should notice that the following characters are legal in the long text name, but it is not legal in the alias used in the DOS prompt. These characters are: plus sign ( ), comma (,), semicolon (;), equal sign (=), and block brackets and close brackets ([]). I don't recommend using these symbols, but if you need to use them. Let us now look at an example of a long file name. I have already said in front, and the subject is actually said that this theme is actually said. Long file names have naturally appeared. The code I have given here is just to provide you with a point. Program List 8.5 is this instance. Program List 8.5 LongName shows how to use long file names in a Windows application
//
// longname.cpp
// Copyleft 1999 by Skyline
//How to create long file names, Plus Some File Io
//
#include & ltwindows.h>
#include & ltstdio.h>
#include & ltconio.h>
// macros
#define Open_ERROR 1000
#define Write_ERROR 1001
#define close_error 1002
#define file_success 1003
// funCS
Void Report (Int Outcome, LPSTR S);
INT FOPENMETHOD (VOID);
Bool CreateFileMethod (Void);
Void showfiles (void); // Program enRty Point
Int main (void)
{
REPORT (FopenMethod (), "File 1");
Report (CreateFileMethod (), "File 2");
Showfiles ();
Printf ("/ NPRESS ANY Key to Continue ...");
_Getch ();
Return 0;
}
// Report Out Come Of File Operation
Void Report (Int Outcome, LPSTR S)
{
Switch (Outcome)
{
Case Open_ERROR:
Printf ("Error Opening% S / N", S);
Break;
Case Write_ERROR:
Printf ("ERROR WRITI% S / N", S);
Break;
Case close_error:
Printf ("Error Closing% S / N", S);
Break;
Case file_success:
Printf ("Success:% S / N", S);
Break;
}
}
// USE Fopen, ETC, To Open Files
Int FopenMethod (Void)
{
File * fp;
Int Num;
FP = fopen ("An Fopen Long Name.txt", "W ");
IF (fp == null)
RETURN OPEN_ERROR;
FOR (NUM = 0; Num <43; Num ) FPRINTF (FP, "Information:% D / N", NUM); if (fclose (fp)! = "0)" RETURN CLOSE_ERROR; RETURN File_suCcess;} // USE CreateFile, ETC, TO Open Files Bool CreateFileMethod (void) {DWORD NUMWRITEN; Char * S = "a little data for the second file"; handle hfile = "createfile (" Createfile Long Name.txt ", generic_write, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile = "= INVALID_HANDLE_VALUE)" return OPEN_ERROR;! if (WriteFile (hFile, s, strlen (s), & NumWritten, NULL)) return WRITE_ERROR; if (CloseHandle (hFile!) ) return CLOSE_ERROR; return FILE_SUCCESS;} // Show all the files in the current directory void ShowFiles (void) {WIN32_FIND_DATA FindData; HANDLE Data; printf ( "/ nDirectory Output: / n"); Data = "FindFirstFile (" *. * ", & FindData);" While (data! = "Invalid_handle_value) {printf ("% s / n ", finddata.cfilename); if (! FindNextFile (Data)) Break;} findclose (data);} The output of this program is as follows. This result has some specific processing methods for directory structures that depend on your system:
Success: File 1
Success: File 2
Directory Output:
.
.
Longname.ncb
Longname.opt
Longname.dsw
Longname.dsp
Longname.cpp
Longname.plg
Debug
An Fopen Long Name.txt
A cretefile long name.txt
Press Any Key to Continue ...
The file operation of the first two line reports is successful: Success: File 1 Success: File 2 If there is some error, then there is no information in successful information but error information. These error information may be generated by the longname program itself. Further information can be learned from the Report routine from longname.cpp. The core of this program is to create the following two files: An Fopen Long Name.txt a createfile long name.txt It uses Win32's own CreateFile API to create the first file, build the first file with the FOPEN routine in the standard C library Two documents. Obviously, the main purpose of this program is to build a long file name. The key issue that is interested in is CreateFileMethod routine:
Bool CreateFileMethod (Void)
{
DWord Numwritten;
Char * s = "a little data for the second file"; handle hfile = cretefile ("a createfile long name.txt",
Generic_Write, 0, NULL, CREATE_ALWAYS,
File_attribute_normal, null;
IF (hfile == invalid_handle_value)
RETURN OPEN_ERROR;
IF (! Writefile (HFile, S, Strlen (s), & number, NULL)
Return Write_ERROR;
IF (! CLOSEHANDE (HFILE))
RETURN Close_ERROR;
Return File_suCcess;
}
This routine uses three functions of Win32 API Createfile, Writefile, and CloseHandle. These functions are the basic file I / O routine of Windows 9x, which uses routines such as _lopen, _lclose, etc. You will find that in the createfile routine, it is valuable to get a handle. Because it can not only open standard disk files, it can also be used to open name pipes, communication resources, and disk devices, and can also be used for console. Of course, in this place uses standard C library routines, many routines are mapped into this function, and this is the implementation of Windows 9X's own file I / O. Grammar:
Createfile
Handle Createfile
LPCSTR LPFILENAME, / / FileName
DWORD dwdesiredAccess, // read_write access
DWORD DWSHAREMODE, / / CAN OTHER Apps Read IT?
LPVOID LPSECurityAttributes, // Security
DWord dwcreationDisposition, // Overwrite, Truncate, ETC
DWORD DWFLAGSANDATTRIBUTES, // Hidden, System, ETC
Handle HTemplateFile // File with Attributes To Copy
);
This is a standard Windows routine that opens and closes the file. You can not only use this function to create a file, but also use it to close an existing file. As mentioned above, it can also be used for naming pipes, communications tools, storage devices, and consoles. This function is one of the most complex calls in the entire Windows API. I don't show this function is inevitably difficult to use, but it is said to pass it. If you want to make a comprehensive understanding of this routine, you can see the online help information. Here I just give enough information to enable you to use this routine to open and close the standard disk file. The first parameter is simple, which is a pointer to a file name. The second parameter can remove the column value: 0: Inquiry the device instead of the actual access device.
Generic_Read: You can read files and mobile file pointers.
Generic_WRITE: You can write files and mobile file pointers.
The third parameter DWSHAREMODE can remove the column value: 0: File sharing is not allowed.
FILE_SHARE_READ: Others can open the file to read the file.
FILE_SHARE_WRITE: Others can open the file to write the file.
Security issues are generally only related to Windows NT, so Windows 9X programmers can set the LPSecurityAttributes parameter to NULL. Parameters dwcreationDisPosition can set the following values: CREATE_NEW failed if the specified file already exists. CREATE_ALWAYS Remote this file if the file already exists.
Open_existing If the file does not exist, this function fails.
Open_ALWAYS Create this file if the file does not exist.
Truncate_existing file is truncated to 0 bytes (used with Generic_Write).
Parameters dwflagsandattributes can set the following values: file_attribute_readonly read-only files.
File_attribute_hidden hides files.
FILE_ATTRIBUTE_SYSTEM can only be used by the operating system.
FILE_ATTRIBUTE_DIRECTORY directory.
File_attribute_archive file (already modified).
FILE_ATTRIBUTE_NORMAL has no attribute, which is only valid when used.
There are also many possible properties that can be used for the createfile function. But for standard file operations, the properties listed here are all properties you need to understand. After learning the console routine, there is no problem with the Writefile function now. Of course, this function is used to write data to the file. This function is defined as follows: BOOL Writefile (Handle Hfile, LPCVOID LPBuffer,
DWORD NNUMBEROFBYTESTOWRITE,
LPDWORD LPNUMBEROFBYTESWRITTEN,
LPVOID LPOVERLAPPED);
For example, in the longname program, use the following line code to write a line of simple string to the file: Writefile (HFile, S, Strlen (s), & number, NULL) where the first parameter is the file returned by the createfile function. Handle. The second parameter is the string you want to write, and the third parameter is the length of the string. The fourth parameter is the number of bytes written. When writing to a nomenclature, socket, the Mail Slot is written, the fifth parameters should use asynchronous I / O mode. When you want to close a file, just pass its handle to the CloseHandle function: CloseHandle (HFILE); Like the WriteFile function, the CloseHandle function is also a Boolean routine when it returns True when it is successful. If you want to read a long file from disk, the best way is to use a standard public dialog box. If you want to do this through an app, you can use the FindFirstFile, FindNetFile, and FindClose functions:
Void ShowFiles (Void)
{
WIN32_FIND_DATA FINDDATA;
Handle Data;
Printf ("/ ndirectory output: / n");
Data = findfirstfile ("*. *", & Finddata);
While (Data! = Invalid_Handle_Value)
{
Printf ("% s / n", findData.cfilename); if (! FindNextFile (Data, & Finddata))
Break;
}
FindClose (data);
}
FindFirstFile uses two parameters. The first parameter is the type of file you are looking for with a mask. For example, you can pass "* .c" or "ab * .txt" to this parameter. If you find this file, the second parameter contains a filling of the Findata structure:
Typedef struct _win32_find_data {// wfd
DWORD dwfileAttributes; // attributes
Filetime FTCREATIONTime; // CREATION TIME
Filetime ftlastaccesstime; // last Opened / Accessed
Filetime ftlastwritetime; // time file was last changed
DWORD NFILESIGH; // Zero, Unless Very Big
Dword nfilesizelow; // the size of the file
DWORD dwreserved0; // reserved for Future Use
DWORD dwreserved1; // reserved for Future Use
Char cfilename [max_path]; // long file name
Char CalternateFileName [16]; // The 8.3 Alias
Win32_find_data;
The content contained in this structure is more than what you want to know about a file. However, if you want to know more than just the last modified time, you still want to know when it is created and the last visit time, then this information is useful. Anyway, when you get the content of a Win32_Find_Data data structure, you will see that the CFileName field can be used to store the long text names retrieved from a directory. The length of the file is recorded in the NFILESZELOW field. If the file is too long, the high part of the number of the file length is placed in the NFileSizeHigh field. You can use this function to find directory, hide files, and other secrets. As long as you check the properties in the first field, you can know the returned file type. The properties used here are the same as the attributes previously described in the CreateFile function. If the FindFirstFile function is called, the handle returned by the function is not equal to the value of InvaliD_Handle_Value. When you have successfully found a file, you may still want to find some other files, its property is the properties of the mask you entered. If you want to find these other files, you can use the FINDNEXTFILE routine: FindNextFile (DATA, & FINDDATA); the first parameter of the FindNextFile function is the handle returned by FindFirstFile, the second parameter is the Win32_find_data structure. Returns true if the function is successful, returns false. You may notice that the While loop in a longname program has been running to the FindNextFile function returns False. Of course, you can also use other ways to construct this "to find the first" cycle, but this program is working very well. When the repeated selection work is processed to all the files in a directory, FindClose should be called to terminate this process. It will turn off the handle used to operate. This needs is derived from a multi-task operating system, and there will be multiple programs in this system to simultaneously call the FindFirstFile function. This means that the operating system is running two similar FindFirstFile loops. Behind this type of processing is achieved by using the handle. 8.6 Console and GUI The following will be introduced below contains two contents: • How to access long file names from Windows GUI. · How to add a GUI dialog to the console application. This sounds complicated but it is easy. What is really hard to do is to pop up an action of a public dialog. Only the basic principles that pop up a public dialog are simply introduced in this section. The functionality of the Condlg program given is to simply pop up a Windows Public dialog, which is the dialog box you see from BCW, MSVC, NotePad, WordPad, and Countless Other applications. . However, it is interested in that this is not doing this in a standard Windows application, but in a console application pops up the dialog. Of course, all this sounds very new, but in a console application and in a GUI program, it is not different from the creation of a public dialog. In fact, the code seen here can be scrapped in a standard Windows application. Program List 8.6 is the source code of Condlg. "CONDLG" represents "console dialog", take this name to show how to pop up a dialog from a console application. Program List 8.6 Condlg.cpp program containing only two routines
//
// Condlg.cpp
// Copyleft 1999 Skyline
//How to pop up a gui dialog from inside a console
//
#include & ltwindows.h>
#include & ltstdio.h> #include & ltconio.h>
#include & ltcommdlg.h>
#pragma Warning (Disable: 4068)
//
// getFileName
//
LPSTR getFileName (HWND HWND, LPSTR SZFILE, INT STRINGSIZE)
{
OpenFileName OFN;
Char SzfileTitle [256];
Char szfilter [256];
STRCPY (SZFilter, "All Files");
STRCPY (& SZFILTER [Strlen (SZFilter) 1], "*. *");
STRCPY (SZFileTitle, "Long File Name Search");
SZFILE [0] = 0;
MEMSET (& OFN, 0, SIZEOF (OpenFileName);
OFN.LSTRUCTSIZE = SIZEOF (OpenFileName);
OFN.HWNDOWNER = hWnd;
OFN.LPSTRFILTER = SZFILTER;
OFN.NFILTERINDEX = 1;
OFN.LPSTRFILE = SZFILE;
OFN.NMAXFILE = STRINGSIZE;
OFN.LPSTRTILE = SZFileTitle;
OFN.FLAGS = OFN_FILEMUSTEXIST;
GetopenFileName (& off)! = true)
{
DWORD Errval;
Char errstr [50] = "CommAN Dialog Error:";
Char BUF [5];
Errval = commdlgextendedError ();
IF (ErrVal! = 0)
{
WSPrintf (buf, "% ld", errval;
STRCAT (Errstr, BUF);
MessageBox (Null, Errstr, "Warning", MB_OK | MB_ICONSTOP);
}
}
Return Szfile;
}
//
// Program Entry Point
//
Void main (void)
{
Char filename [MAX_PATH * 2];
Hwnd hwnd;
Printf ("Press Any Key To See Dialog";
_Getch ();
HWnd = getForegroundWindow ();
GetFileName (hwnd, filename, max_path * 2);
Printf ("/ N / NYOU CHOOSE:% S", FileName);
_Getch ();
}
When you run this Console Dialog program, you first appear a console window. In the window is a simple description, tell you if you want to see the dialog, just press any key. This part of the program does not have other functions in addition to this prompt to the user. I hope that you should know clearly, now you are in a console application, you will see it launched a Windows Public dialog. Without these prompt information, the relationship between the two windows may be unclear. When you press any key, a dialog appears, you can browse the directory on your hard drive. Note that it is also able to see the long text name. When you read these file names, you can select a file, then press the OK button to return to the console window. The name you choose is displayed in a standard text mode string. The key here is that the public dialog can also let you access long file names, you don't need to do any special things to do this. Just start a dialog box, it will automatically browse and retrieve the long file name. The core part of this program is running around the following line of code: hWnd = getForeGroup (); this line code returns to the HWnd of the console. You can also retrieve this handle if you need it. Once you get the handle of the console window, you don't have anything. The actual action that pops up a public dialog is quite complicated because there is a batch of parameters to be specified. In the following part, this function will be discussed in-depth discussion, now I only introduce some points. One way is to give you the routine here as a black box, just copy it into other applications, and pass it to a valid HWnd, a buffer of the file name and the length of the buffer. Note that this routine first clears the file name. If you want to display the file name you transmitted when the dialog is first appearing, just remove the following line of code: SZFILE [0] = 0; create an Open File dialog box: • OpenFileName The structure is clear. · Fill in information to each field you want to use. · Pass this structure to the getopenfilename function. Windows will pop up this dialog and return the name selected by the user, then pass the name in the lpstrfile field to you. Note that in the OpenFileName structure, there is a field initialdir to specify the directory you want to browse. To learn more about find OpenFileName and getopenFileName in online help. 8.7 Debug Tool: From a GUI to a console window Now, you know how to get a GUI interface from a console program. Here you will introduce an opposite way: pop up a console window in a standard window. I put this theme in the end, I don't say it is the least important. In fact, a console window in GUI is a great advantage in the Windows 9x interface. Of course, you will not do this as a product issued as a product, but when we are deeply embarrassed in the chaos of the chaotic debug period, this approach is very useful. Program List 8.7 Code of GuitExt.cpp Program
//
// GuitExt.cpp
// Copyleft 1999 Skyline
// GuitExt Windows Program
//
#define strict
#define Win32_Lean_and_mean
#include & ltwindows.h>
#include & ltwindowsx.h>
#include & ltstdio.h>
#include "guitext.h"
#include "conbox.h"
#pragma Warning (Disable: 4068)
// --------------------------------------- // Interface
/ / ---------------------------------------
Static char szappname [] = "guitext";
Static hwnd mainwindow;
Static hinstance hinstance;
// ----------------------------------------
// Initialization
// ----------------------------------------
//
// Program Entry Point.
//
#pragma argsused
Int WinApi Winmain (Hinstance Hinst, Hinstance Hprevinstance,
LPSTR LPSZCMDPARAM, INT NCMDSHOW)
{
MSG msg;
IF (! hprevinstance)
IF (! register (hinst))
Return False;
IF (! Create (hinst, ncmdshow)
Return False;
While (GetMessage (& MSG, NULL, 0, 0))
{
TranslateMessage (& MSG);
DispatchMessage (& MSG);
}
Return msg.wparam;
}
// register the window
Bool Register (Hinstance Hinst)
{
WNDCLASS WNDCLASS;
WNDCLASS.Style = CS_HREDRAW | CS_VREDRAW;
WNDCLASS.LPFNWNDPROC = WNDPROC;
WNDCLASS.CBCLSEXTRA = 0;
Wndclass.cbWndextra = 0;
WNDCLASS.HINSTANCE = HINST;
WNDCLASS.HICON = LOADICON (NULL, IDI_Application);
WNDCLASS.HCURSOR = loadingcursor (null, idc_arrow);
Wndclass.hbrbackground = (Hbrush) (Color_Window 1);
WNDCLASS.LPSZMENUNAME = "GuitExtMenu";
Wndclass.lpszclassName = szappname;
Return RegisterClass (& WNDCLASS);
}
// Creat the window
HWnd Create (Hinstance Hinst, Int ncmdshow)
{
Hinstance = hinst;
HWND HWND = CREATEWINDOWEX (0, Szappname, Szappname,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, HINST, NULL;
IF (hwnd == null)
Return False;
ShowWindow (HWND, NCMDSHOW);
UpdateWindow (HWND);
Return hwnd;
}
// ---------------------------
// WndProc and Implementation
// ---------------------------
//
// the window procedure
//
Lresult Callback WndProc (HWND HWND, UINT MESSAGE, WPARAM WPARAM, LPARAM LPARAM)
{
Switch (Message)
{
Handle_msg (hwnd, wm_destroy, skyline_ondestroy);
Handle_msg (hwnd, wm_command, skyline_oncommand);
DEFAULT:
Return Skyline_DefProc (HWND, Message, WPARAM, LPARAM);
}
}
///
// Handle WM_DESTROY
///
#pragma argsused
Void Skyline_Ondestroy (HWND HWND)
{
PostquitMessage (0);
}
///
// WM_COMMAND: POP UP UP UPUE WINDOW
///
#pragma argsused
Void Skyline_oncommand (HWND HWND, INT ID,
HWND HWNDCTL, UINT CODENOTIFY)
{
Char s [100];
IF (id == cm_console)
{
Allocconsole ();
INITSTDOUT ();
CLRSCR (GoldBlue);
Writexy (1, 1, "console ststus report);
Sprintf (s, "hwnd% x hinstance% x id% d", hwnd, hinstance, id);
Writexy (1, 2, s);
Writexy (1,3, "any key to close");
WaitforKeyPress ();
FREECONSOLE ();
}
}
Program List 8.8 The main header of the GuitExt program
//
// GuitExt.h
// Copyleft 1999 Skyline
//
#define cm_console 101
Bool register (Hinstance Hinst);
HWND CREATE (Hinstance Hinst, Int ncmdshow);
LResult Callback WndProc (HWND HWND, UINT MESSAGE,
WPARAM WPARAM, LPARAM LPARAM;
#define skyline_defproc DefWindowProc
Void Skyline_ONDESTROY (HWND HWND);
Void Skyline_oncommand (HWND HWND, INT ID,
HWND HWNDCTL, UINT CODENOTIFY;
Program List 8.9 Utility Routines for Accessing Consoles
//
// conbox.cpp
// Copyleft 1999 Skyline
// Routines for Handling Screen Io from a console
//
#include & ltwindows.h>
Static handle hout;
Static handle hin;
///
// Initialize Handle: Call this Routine Before Using Others
///
Void Initstdout (Void)
{
Hout = getstdhandle (std_output_handle);
Hin = getstdhandle (std_input_handle);
}
///
// gotoxy Move Cursor To Col, Row
///
Void gotoxy (int x, int y)
{
Coord C;
C.x = x;
C.Y = Y;
SetConsolecursorPosition (Hout, C);
///
// Writexy
///
Void Writexy (int X, int y, lpstr s)
{
DWORD RESULT;
Gotoxy (x, y);
Writeconsole (HOUT, S, STRLEN (S), & Result, NULL);
}
//
// Blank out a line of text
//
Void Blankline (Short Y)
{
DWord Numwritten;
Coord C;
C.x = 0;
C.Y = Y;
FillconsoleOutputCharacter (Hout, '', 80, C, & Numwritten;
}
//
// clear the screen
//
Void CLRSCR (Word Attr)
{
DWord Numwritten;
Coord C;
C.x = 0;
C.y = 0;
FillconsoleOutputCharacter (Hout, '', 80 * 25, C, & Numwritten);
FillConsoleOutputttribute (Hout, Attr, 80 * 25, C, & Numwritten);
}
//
// Write a line of text
//
Void Write (LPSTR S)
{
DWORD RESULT;
Writeconsole (HOUT, S, STRLEN (S), & Result, NULL);
}
//
// Wait for a Key
//
Void WaitforKeyPress (Void)
{
DWORD RESULT;
INPUT_RECORD BUF;
DO
{
ReadconsoleInput (Hin, & Buf, 1, & Result);
} while (buf.eventtype! = key_event);
}
Program List 8.10 Header file of the application routine used in Conbox.cpp
//
// conbox.h
// Copyleft 1999 Skyline
//
#define bw foreground_red | Foreground_green | Foreground_blue
#define goldblue foreground_green | Foreground_red | /
Foreground_INTENSITY | Background_Blue
#define pb foreground_red | Foreground_blue
#define GB Foreground_green
Void Initstdout (Void);
Void Goyoxy (int X, int y, lpstr s, word attr);
Void Writexy (int X, int y, lpstr s);
Void Blankline (Short Y);
Void CLRSCR (Word Attr);
Void Write (LPSTR S);
Void WaitforKeyPress (Void);
Program List 8.11 GuitExt Source File
//
// GuitExt.rc
//
#include "guitext.h"
GuitextMenu Menu
Begin
Menuitem "Run Console" CM_CONSOLE
End
This program is a standard Windows application. It contains a main window, where there is only one menu option. If you select this menu option, a console window will appear, which shows some standard debugging information. Especially it shows the Hinstance and Hwnd of the program. When a menu item is selected, the calling code is as follows: void Skyline_oncommand (HWND HWND, INT ID,
HWND HWNDCTL, UINT CODENOTIFY)
{
Char s [100];
IF (id == cm_console)
{
Allocconsole ();
INITSTDOUT ();
CLRSCR (GoldBlue);
Writexy (1, 1, "console ststus report);
Sprintf (s, "hwnd% x hinstance% x id% d", hwnd, hinstance, id);
Writexy (1, 2, s);
Writexy (1,3, "any key to close");
WaitforKeyPress ();
FREECONSOLE ();
}
}
This program can almost do not explain again. This code simply assigns a console and writes the output on it above so that it can be used to debug. In particular, it shows the current value of Hinstance and HWnd so you can often check these values is 0. This is a simple confirmation method. All routines I have used to operate are all of the WinCon.h part of the Win32 API. However, I put most packages of these routines in some functions, these functions take a relatively simple name, such as Writexy and ClrsCR. You should clearly understand the functions of these routines. For example, the following routines can be used to clear the screen and set the screen to a particular color:
Void CLRSCR (Word Attr)
{
DWord Numwritten;
Coord C;
C.x = 0;
C.y = 0;
FillconsoleOutputCharacter (Hout, '', 80 * 25, C, & Numwritten);
FillConsoleOutputttribute (Hout, Attr, 80 * 25, C, & Numwritten);
}
This routine assumes that you want to clear a 80x25 body screen. As mentioned earlier, if you need, you can make precise calculations on the size of the current screen. The CLRSCR routine has only one parameter that is used to specify a specific set of foregrounds and background colors. These colors are described below:
#define bw foreground_red | Foreground_green | Foreground_blue
#define goldblue foreground_green | Foreground_red | /
Foreground_INTENSITY | Background_Blue
#define pb foreground_red | Foreground_blue
#define GB Foreground_green
BW represents a standard black and white screen. Another function to be mentioned is WaitforKeyPress:
Void WaitforKeyPress (Void)
{
DWORD RESULT;
INPUT_RECORD BUF;
DO
{
ReadconsoleInput (Hin, & Buf, 1, & Result);
} while (buf.eventtype! = key_event);
}