• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            我住包子山

            this->blog.MoveTo("blog.baozishan.in")

            [基礎]Win32 Console Applications - Part 2 of 6 from adrianxw.dk

            Win32 Console Applications - Part 2.

            I started part 1 of this tutorial by showing the classic "Hello Worlrd!" program. The output looked like this.

            Hello World

            By default, Windows places the path of the executable in the window title. You can change this to a word or phrase of your choice. Here is the Hello World! program modified to do this.

            #include <windows.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                SetConsoleTitle("Hello!");
                cout << "Hello World!" << endl;
                return 0;
            }
            

            Notice I've now added the windows.h header to the program, and a call to SetConsoleTitle(). The output now looks like this.

            Hello World

            Later on, we'll see that knowing the name of your window can be useful, and setting it yourself is, of course, an easy way of knowing it!

            As an aside, almost all of the API routines return a status indicating success or failure. For clarity of the example code in these tutorials, I am not checking this value. To be more professional, you should check the return values of API routines you call. Even if you cannot recover from the error, it is often useful in debugging to know what routine failed, and if possible, why. This program shows the checking of the return status and aborts the program if the routine fails, (note the inclusion of process.h for the exit() API routine). You should refer to your compiler's help or MSDN to see what the return values of a routine are.

            #include <windows.h>
            #include <process.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                int Status;
            
                Status = SetConsoleTitle("Hello!");
                if (Status == 0)
                {
                    Status = GetLastError();
                    cout << "SetConsoleTitle() failed! Reason : " << Status << endl;
                    exit(Status);
                }
            
                cout << "Hello World!" << endl;
                return 0;
            }
            
            ----------

            All consoles have 3 "standard handles" and many of the console handling functions require a "handle" to perform I/O.

            A "handle" is simply a 32 bit integer. It is the way Windows differentiates between objects of the same type. Consider the console, it has a title bar, minimize, maximize and close buttons, one or more scroll bars, etc. It is, when you think about it, quite a complicated thing, and somewhere there must be a lot of data that the system is using to make it all work. Windows hides all of that complexity from you, you can play with all this data if you want to of course, but the point here is, you don't have to if you don't want to. Windows looks after it all for you, and all you have to do is tell it the handle of whatever it is you want to use. Once you get into full Windows programming, you'll find a lot of things are used by supplying a "handle". If you don't understand right now, don't worry about it, a handle is easy to get, and easy to use.

            To get the standard handles, declare variable of type HANDLE and initialise them with a call to GetStdHandle(). This program, (which doesn't actually do anything!), illustrates the process. We'll use the standard handles later.

            #include <windows.h>
            
            int main()
            {
                HANDLE hIn;
                HANDLE hOut;
                HANDLE hError;
            
                hIn = GetStdHandle(STD_INPUT_HANDLE);
                hOut = GetStdHandle(STD_OUTPUT_HANDLE);
                hError = GetStdHandle(STD_ERROR_HANDLE);
            
                return 0;
            }
            

            The standard input handle is used with routines that read data from a console, the standard output handle with routines that send data to a console. The standard error handle also outputs to the console by default, and frankly is not used very much, just be aware of it.

            There are a couple of routines ReadConsole() and WriteConsole() that perform I/O using these handles, but for now at least, we'll continue with the standard C++ I/O functions.

            ----------

            Now we've got the handles, lets do something with them, let's move the cursor around. To do this we'll need to use a COORD structure. This is a very simple structure containing an x and y coordinate. It is declared like this.

            typedef struct _COORD {
                SHORT X;
                SHORT Y;
            } COORD; 
            

            To move the cursor, you simply set up the COORD to the coordinates you want the cursor moved to and call the SetConsoleCursorPosition() API function. Here is a simple program which does just that.

            #include <windows.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                HANDLE hOut;
                int i;
                COORD Position;
            
                hOut = GetStdHandle(STD_OUTPUT_HANDLE);
            
                for(i=0; i<10; i+=2)
                {
                    Position.X = i;
                    Position.Y = i;
                    SetConsoleCursorPosition(hOut,
                                             Position);
                    cout << "*" << flush;
                }
            
                return 0;
            }
            

            The output looks like this.

            Move Cursor

            As you see, each iteration of the loop moves the cursor two rows down and two columns right. To return the cursor to the "home" position, (top left corner), send it to (0,0). Creative use of this function can give pleasing effects.

            ----------

            The next routine I want to show you is FillConsoleOutputCharacter(). This routine allows you to write a whole load of characters to the console in one go. The function prototype is shown here.

            BOOL FillConsoleOutputCharacter(
              HANDLE hConsoleOutput,
              TCHAR cCharacter,
              DWORD nLength,
              COORD dwWriteCoord,
              LPDWORD lpNumberOfCharsWritten
            );
            

            A bit more complicated then any of the routines we've used so far, but really very easy to use. The first parameter is the handle to the output buffer, you know how to get that. The next is the character you want to write, easy enough. The next, is how many times you want it to write the character out, still easy. Next is a COORD telling it where to start, we've already covered that. Finally, the routine wants a place where it can tell you how many characters it actually wrote, this has to be therefore, the address of a variable in your program. You may be wondering why this argument is there at all, but consider the situation where your screen buffer is, for example, 5000 characters long. If you tell the routine to output 5100, it will not error, it will fill the 5000 characters, and then tell you that it did that by setting the value accordingly. If you're not interested, ignore it, but you must supply a place for the routine to use, in this case, I've passed the address of the "Written" variable like this &Written.

            This program uses FillConsoleOutputCharacter() to draw a line of 15 "X" characters starting at (4,4), the unsuprising output of the program is also shown below.

            #include <windows.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                HANDLE hOut;
                COORD Position;
                DWORD Written;
            
                hOut = GetStdHandle(STD_OUTPUT_HANDLE);
            
                Position.X = 4;
                Position.Y = 4;
            
                FillConsoleOutputCharacter(hOut,
                                           'X',
                                           15,
                                           Position,
                                           &Written);
            
                return 0;
            }
            
            Fill Console

            See what happens if I change the call to output 150 instead of 15 characters, (I've shrunk the picture to make it load faster - changing the call did not change the screen resolution!!!).

            Fill Console

            The point to note is that when the routine reached the end of the line, it continued at the beginning of the line below. Suppose, instead of line 5 column 5 I'd said (0,0), and suppose I'd used a space character instead of an 'X', and suppose I'd told it to draw enough characters to completely fill the screen buffer - hey - I've cleared the screen! Clearing the screen is THE most common console related question that comes up in the forums, there's the answer.

            ----------

            It is also possible to read one or more characters from a specific position in the screen buffer. To do that, we use the ReadConsoleOutputCharacter() API routine. This routine has very similar parameters to the last, it's prototype is shown here.

            BOOL ReadConsoleOutputCharacter(
              HANDLE hConsoleOutput,
              LPTSTR lpCharacter,
              DWORD nLength,
              COORD dwReadCoord,
              LPDWORD lpNumberOfCharsRead 
            );
            

            As before, the first is the standard handle. Next, remember, we are reading now, so the routine wants somewhere to write the information to, so it needs a pointer to a place where it can store characters. The rest of the parameters are as before, the number of characters to process, the start point, and a pointer to a place it can write the actual number read.

            This program uses the routine twice, once to retrieve the single character at the (0,0) position, and a second time to retrieve 5 characters starting from position (4,0). If the number of characters requested is longer than the current line, reading continues from the first character of the line below as before. Again, as before, if the number requested is more than there are in the buffer, the characters up to the end of the buffer are returned, the actual number appearing in the final parameter.

            #include <windows.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                HANDLE hOut;
                char Letter;
                char Letters[5];
                COORD Where;
                DWORD NumRead;
                int i;
            
                hOut = GetStdHandle(STD_OUTPUT_HANDLE);
            
                cout << "A line of little consequence." << endl;
            
                Where.X = 0;
                Where.Y = 0;
                ReadConsoleOutputCharacter(hOut,
                                           &Letter,
                                           1,
                                           Where,
                                           &NumRead);
                cout << "Letter at (0,0) is " << Letter << endl;
            
                Where.X = 4;
                ReadConsoleOutputCharacter(hOut,
                                           Letters,
                                           5,
                                           Where,
                                           &NumRead);
                cout << "5 letters starting from (4,0) ";
                for (i=0; i<5; i++)
                {
                    cout << Letters[i];
                }
                cout << endl;
            
                return 0;
            }
            

            The output from the program looks like this.

            ReadConsoleOutputCharacter

            It would have been quite permissable to dimension the Letters array to 6, read the 5 characters from the console then manually set the final character to NULL. In that way, the cout could have taken the name of the string, (as it is now NULL terminated), instead of writing the characters out individually in a loop.

            In the next part of the tutorial, we'll look at the limited graphical capabilities of consoles, drawing lines, boxes and grids.

            Win32 Console Applications - Part 2.

            I started part 1 of this tutorial by showing the classic "Hello Worlrd!" program. The output looked like this.

            Hello World

            By default, Windows places the path of the executable in the window title. You can change this to a word or phrase of your choice. Here is the Hello World! program modified to do this.

            #include <windows.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                SetConsoleTitle("Hello!");
                cout << "Hello World!" << endl;
                return 0;
            }
            

            Notice I've now added the windows.h header to the program, and a call to SetConsoleTitle(). The output now looks like this.

            Hello World

            Later on, we'll see that knowing the name of your window can be useful, and setting it yourself is, of course, an easy way of knowing it!

            As an aside, almost all of the API routines return a status indicating success or failure. For clarity of the example code in these tutorials, I am not checking this value. To be more professional, you should check the return values of API routines you call. Even if you cannot recover from the error, it is often useful in debugging to know what routine failed, and if possible, why. This program shows the checking of the return status and aborts the program if the routine fails, (note the inclusion of process.h for the exit() API routine). You should refer to your compiler's help or MSDN to see what the return values of a routine are.

            #include <windows.h>
            #include <process.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                int Status;
            
                Status = SetConsoleTitle("Hello!");
                if (Status == 0)
                {
                    Status = GetLastError();
                    cout << "SetConsoleTitle() failed! Reason : " << Status << endl;
                    exit(Status);
                }
            
                cout << "Hello World!" << endl;
                return 0;
            }
            
            ----------

            All consoles have 3 "standard handles" and many of the console handling functions require a "handle" to perform I/O.

            A "handle" is simply a 32 bit integer. It is the way Windows differentiates between objects of the same type. Consider the console, it has a title bar, minimize, maximize and close buttons, one or more scroll bars, etc. It is, when you think about it, quite a complicated thing, and somewhere there must be a lot of data that the system is using to make it all work. Windows hides all of that complexity from you, you can play with all this data if you want to of course, but the point here is, you don't have to if you don't want to. Windows looks after it all for you, and all you have to do is tell it the handle of whatever it is you want to use. Once you get into full Windows programming, you'll find a lot of things are used by supplying a "handle". If you don't understand right now, don't worry about it, a handle is easy to get, and easy to use.

            To get the standard handles, declare variable of type HANDLE and initialise them with a call to GetStdHandle(). This program, (which doesn't actually do anything!), illustrates the process. We'll use the standard handles later.

            #include <windows.h>
            
            int main()
            {
                HANDLE hIn;
                HANDLE hOut;
                HANDLE hError;
            
                hIn = GetStdHandle(STD_INPUT_HANDLE);
                hOut = GetStdHandle(STD_OUTPUT_HANDLE);
                hError = GetStdHandle(STD_ERROR_HANDLE);
            
                return 0;
            }
            

            The standard input handle is used with routines that read data from a console, the standard output handle with routines that send data to a console. The standard error handle also outputs to the console by default, and frankly is not used very much, just be aware of it.

            There are a couple of routines ReadConsole() and WriteConsole() that perform I/O using these handles, but for now at least, we'll continue with the standard C++ I/O functions.

            ----------

            Now we've got the handles, lets do something with them, let's move the cursor around. To do this we'll need to use a COORD structure. This is a very simple structure containing an x and y coordinate. It is declared like this.

            typedef struct _COORD {
                SHORT X;
                SHORT Y;
            } COORD; 
            

            To move the cursor, you simply set up the COORD to the coordinates you want the cursor moved to and call the SetConsoleCursorPosition() API function. Here is a simple program which does just that.

            #include <windows.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                HANDLE hOut;
                int i;
                COORD Position;
            
                hOut = GetStdHandle(STD_OUTPUT_HANDLE);
            
                for(i=0; i<10; i+=2)
                {
                    Position.X = i;
                    Position.Y = i;
                    SetConsoleCursorPosition(hOut,
                                             Position);
                    cout << "*" << flush;
                }
            
                return 0;
            }
            

            The output looks like this.

            Move Cursor

            As you see, each iteration of the loop moves the cursor two rows down and two columns right. To return the cursor to the "home" position, (top left corner), send it to (0,0). Creative use of this function can give pleasing effects.

            ----------

            The next routine I want to show you is FillConsoleOutputCharacter(). This routine allows you to write a whole load of characters to the console in one go. The function prototype is shown here.

            BOOL FillConsoleOutputCharacter(
              HANDLE hConsoleOutput,
              TCHAR cCharacter,
              DWORD nLength,
              COORD dwWriteCoord,
              LPDWORD lpNumberOfCharsWritten
            );
            

            A bit more complicated then any of the routines we've used so far, but really very easy to use. The first parameter is the handle to the output buffer, you know how to get that. The next is the character you want to write, easy enough. The next, is how many times you want it to write the character out, still easy. Next is a COORD telling it where to start, we've already covered that. Finally, the routine wants a place where it can tell you how many characters it actually wrote, this has to be therefore, the address of a variable in your program. You may be wondering why this argument is there at all, but consider the situation where your screen buffer is, for example, 5000 characters long. If you tell the routine to output 5100, it will not error, it will fill the 5000 characters, and then tell you that it did that by setting the value accordingly. If you're not interested, ignore it, but you must supply a place for the routine to use, in this case, I've passed the address of the "Written" variable like this &Written.

            This program uses FillConsoleOutputCharacter() to draw a line of 15 "X" characters starting at (4,4), the unsuprising output of the program is also shown below.

            #include <windows.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                HANDLE hOut;
                COORD Position;
                DWORD Written;
            
                hOut = GetStdHandle(STD_OUTPUT_HANDLE);
            
                Position.X = 4;
                Position.Y = 4;
            
                FillConsoleOutputCharacter(hOut,
                                           'X',
                                           15,
                                           Position,
                                           &Written);
            
                return 0;
            }
            
            Fill Console

            See what happens if I change the call to output 150 instead of 15 characters, (I've shrunk the picture to make it load faster - changing the call did not change the screen resolution!!!).

            Fill Console

            The point to note is that when the routine reached the end of the line, it continued at the beginning of the line below. Suppose, instead of line 5 column 5 I'd said (0,0), and suppose I'd used a space character instead of an 'X', and suppose I'd told it to draw enough characters to completely fill the screen buffer - hey - I've cleared the screen! Clearing the screen is THE most common console related question that comes up in the forums, there's the answer.

            ----------

            It is also possible to read one or more characters from a specific position in the screen buffer. To do that, we use the ReadConsoleOutputCharacter() API routine. This routine has very similar parameters to the last, it's prototype is shown here.

            BOOL ReadConsoleOutputCharacter(
              HANDLE hConsoleOutput,
              LPTSTR lpCharacter,
              DWORD nLength,
              COORD dwReadCoord,
              LPDWORD lpNumberOfCharsRead 
            );
            

            As before, the first is the standard handle. Next, remember, we are reading now, so the routine wants somewhere to write the information to, so it needs a pointer to a place where it can store characters. The rest of the parameters are as before, the number of characters to process, the start point, and a pointer to a place it can write the actual number read.

            This program uses the routine twice, once to retrieve the single character at the (0,0) position, and a second time to retrieve 5 characters starting from position (4,0). If the number of characters requested is longer than the current line, reading continues from the first character of the line below as before. Again, as before, if the number requested is more than there are in the buffer, the characters up to the end of the buffer are returned, the actual number appearing in the final parameter.

            #include <windows.h>
            #include <iostream>
            using namespace std;
            
            int main()
            {
                HANDLE hOut;
                char Letter;
                char Letters[5];
                COORD Where;
                DWORD NumRead;
                int i;
            
                hOut = GetStdHandle(STD_OUTPUT_HANDLE);
            
                cout << "A line of little consequence." << endl;
            
                Where.X = 0;
                Where.Y = 0;
                ReadConsoleOutputCharacter(hOut,
                                           &Letter,
                                           1,
                                           Where,
                                           &NumRead);
                cout << "Letter at (0,0) is " << Letter << endl;
            
                Where.X = 4;
                ReadConsoleOutputCharacter(hOut,
                                           Letters,
                                           5,
                                           Where,
                                           &NumRead);
                cout << "5 letters starting from (4,0) ";
                for (i=0; i<5; i++)
                {
                    cout << Letters[i];
                }
                cout << endl;
            
                return 0;
            }
            

            The output from the program looks like this.

            ReadConsoleOutputCharacter

            It would have been quite permissable to dimension the Letters array to 6, read the 5 characters from the console then manually set the final character to NULL. In that way, the cout could have taken the name of the string, (as it is now NULL terminated), instead of writing the characters out individually in a loop.

            In the next part of the tutorial, we'll look at the limited graphical capabilities of consoles, drawing lines, boxes and grids.

            posted on 2006-07-20 22:46 Gohan 閱讀(706) 評論(0)  編輯 收藏 引用 所屬分類: C++

            97久久婷婷五月综合色d啪蜜芽| 久久亚洲精品无码AV红樱桃| 久久国产精品一国产精品金尊| 久久精品国产2020| 亚洲国产精品成人AV无码久久综合影院| 色成年激情久久综合| 91精品国产色综久久| 久久国产成人精品国产成人亚洲| 久久亚洲av无码精品浪潮| 久久精品夜色噜噜亚洲A∨| 亚洲精品综合久久| 日韩欧美亚洲综合久久| 亚洲乱码精品久久久久..| 久久中文骚妇内射| 久久综合九色综合欧美狠狠| 久久久噜噜噜久久| 久久久久亚洲AV片无码下载蜜桃 | 亚洲日本va午夜中文字幕久久| 亚洲精品成人久久久| 久久久一本精品99久久精品88| 91久久婷婷国产综合精品青草| 久久精品国产只有精品66| 欧美伊人久久大香线蕉综合 | 国产精品18久久久久久vr| 久久99精品久久久久久9蜜桃| 亚洲精品无码久久不卡| 99久久人妻无码精品系列蜜桃| 国产精品成人久久久久久久| 波多野结衣AV无码久久一区| 久久99国产精品久久99| 伊人情人综合成人久久网小说| 国产三级久久久精品麻豆三级 | 午夜精品久久久久久影视777| 久久99精品久久久久婷婷| 伊人色综合久久天天人守人婷| 国产成人精品久久二区二区| 久久精品aⅴ无码中文字字幕不卡| 久久亚洲国产欧洲精品一| 性做久久久久久久| 日韩亚洲国产综合久久久| 美女写真久久影院|