Win32 Learning Notes Chapter 4 Output Text

zhaozj2021-02-16  42

Win32 learning notes

Author: Jiang Xuezhe (netsail0@163.net)

Textbook: Windows Program Design (Fifth Edition) Peking University Press [United States] Charles Petzold Co., Ltd. ¥: 160

Environment: Windows2000 PRO Internet Explorer 6.0 DirectX8.1 Visual C 6.0

Tint Jiang Computer Program Group (http://chulsoft.xiloo.com) Copyright, reprint, please explain the source ----------------------- ------------------------------------------- [Chapter 4 Output Text - 2】

The fourth chapter is too long, so I can only be divided into two paragraphs. This is the second paragraph. And the difficulty is also increased. Many stuff I can't explain it clearly. So you can only do what I can. Written very well on the book. Most of this chapter have many books on the book. I am a little doubtful to write a learning note.

Our program urgently needs a vertical scroll bar, and there is no need to horizontally scroll. Joining a vertical scroll bar is easy. CreateWindow () has a parameter is WS_OVERLAPPEDWINDOW, we will change it to:

WS_OVERLAPPEDWINDOW | WS_VSCROLL

Yes.

The window process will receive a WM_CREATE message when calling CREATEWINDOW (). The WM_CREATE section of the second program is similar to the first program, but the second program is more than two functions:

SetscrollRange (HWND, SB_VERT, 0, Numlines - 1, False); SetscrollPos (HWND, SB_VERT, IVSCROLLLPOS, TRUE);

Because IVScrollPos is a static variable, it is 0 in its initial value. The function function of the first line is to determine the range of the scroll bar, and the function of the second line is the location of the ruler. At this time, the value of IVScrollPos is 0. Therefore, the position of the scroll bar is of course 0. There is a Numlines in the first function. This stuff is defined in sysmets.h header files. Find a look.

In order to help process the WM_VSCROLL message, the window process defines a static variable IVScrollPos, which is the current location of the scroll box. For SB_Lineup, SB_LINEDown only needs to adjust the scroll box to a unit. For SB_PAGEUP, SB_PAGEDOWN, move the location of the Cyclient / Cychar unit. The new scroll position for SB_THUMBPSITION is the high word of WPARAM. SB_ENDSCROLL, SB_THUMBTRACK message is ignored.

Case WM_VSCROLL: Switch (WPARAM) {CASE SB_LINEUP: ivscrollpos - = 1; Break; Case SB_Linedown: ivscrollpos = 1; Break;

Case SB_Pageup: ivscrollpos - = cyclient / cychar; Break;

Case SB_PAGEDOWN: IVSCROLLPOS = cyclient / cychar;

Case Sb_thumbPosition: ivscrollpos = half;

DEFAULT: BREAK;

I think the code above is simple. First use the loword () macro to get the notification code. Then do different actions for various notices. The notification code is a position IVScrollPOS to rise when SB_LineUp, which is minus one. Why do you ask me? Because the more it is, the closer to 0! The top is 0, the bottom is Numlines-1. Then ivscrollpos = max (0, min (ivscrollpos, numlines-1);

Why do we need this statement? Suppose, the current ivscrollpos value is 0, this time the program has received a SB_LineUp notification code, so that IVScrollPos has become -1. The problem is that the position of the scroll box cannot be -1, and the position of the scroll box has a range, that is, from 0 to Numlines-1, so we use the above statement.

The value of the above statement is Numlines-1 when IVScrollPos is larger than Numlines-1. When IVScrollPos is less than 0, the value of the above statement is 0. This has been strictly controlled between 0 and Numline-1 since the value of IVScrollpos.

IF (ivscrollpos! = getScrollpos (hwnd, sb_vert)) {setscrollpos (hwnd, sb_vert, ivscrollpos, true); invalidateERECT (hwnd, null, true);}

Although it is so lively, the position of the scroll bar has not changed at all. We changed just integer variables IVScrollPos. Below we have to change the position of the scroll box with setscrollpos ().

Setscrollpos (HWND, SB_VERT, IVSCROLLPOS, TRUE);

The position of this sub-rolling frame is truly IVScrollpos. Then invoke inValidateERECT () so that the entire client area is invalid, so that a WM_PAINT message has been generated. Slowly, there is still an IF statement that is not explained. Sometimes I do some operations on the scroll box, but the final position of the scroll bar has not changed. At this time, there is no need to call the scroll bar at all, but if there is no this IF, the program will redo the scroll bar. This is an efficiency problem. If your machine is configured very high, you can use this if statement. My machine is not.

The WM_Paint section of the second program is unique to the first program is

The third parameter y of TextOut ().

Y = cychar * (i - ivscrollpos);

When the rolling frame is 0, the statement above is nothing difference with this chapter, the first program is:

y = cychar * i;

but! ! ! When the rolling frame position is 1, the above statement becomes:

Y = cychar * (-1)

That is, the display position of the first line of text is cychar * (-1). At this time, the program still shows the Numline line text, but the first line of text is displayed on the customer area. So we can't see the first line of text. The second line of text replaced the original position of the first line of text.

This is reasonable. We shifted the scroll bar position, so the first line of text visited, the second line of text replaced the position of the original first line of text, displayed in the customer area. So we just understand

Y = cychar * (i - ivscrollpos);

This statement is ok. This statement is the focus of the second program! ! ! ! I guess ~~~~~~~~~~

The book says that these programs are very low. These spam code is just to make us easy. Don't use these methods when you really write software, it is very failed! Below is the last program code of this chapter. First reconsider the method of refresh the client area after the WM_VScroll message.

After processing the scroll message, Sysmets2 does not refresh the client area, which calls invalidateect () to make the customer area invalid. This will generate a WM_PAINT message. The program refreshes the entire client area when receiving the WM_PAINT message, so it is best to complete all customer district drawings during the WM_PAINT message. If you also draw in other parts of the program, you will be likely to repeat the code.

It is just to mark the window customer area as invalid to generate WM_PAINT messages, which may not be completely satisfactory for some applications. After invoing InvalIDateRect (), Windows puts the WM_PAINT message into the message queue and finally processes it by the window process. But the priority of WM_PAINT is very low. If the system has other actions at this time, this WM_PAINT message has to wait for a while, such, when the dialog disappears, there will be blank "holes". The program is still waiting for refreshing its window.

If you want to refresh the invalid area immediately, you can call UpdateWindow after calling inValidateRect ().

UpdateWindow () will cause the WM_PAINT message call window process. This WM_Paint does not enter the message queue and is processed directly by the window process. The window process exits immediately after refresh.

Sysmets2 works very well, but it just imitates the scroll bar in other programs and is very efficient. Soon I will show a new version to improve its shortcomings. The new version does not use the four scroll bar functions currently discussed, which will use new functions in the Win32 API.

The MSDN's scroll file indicates setScrollRange (), setscrollpos (), getScrollRange (), getScrollPos () is outdated.

Two scroll strips described in Win32 API are called setscrollinfo (), getScrollInfo (). These two functions can complete all the functions of previous functions and add two new features.

The first characteristic involves the size of the scroll box. The size of the scroll box in the sysmets2 program is constant. However, many of the rolling frames in a multi-Windows program are proportional to the size of the document displayed by the window.

You can use SetscrollInfo () to set the page size, which sets the size of the scroll box, such as the Sysmets3 program that will be seen.

The getScrollInfo () function adds the second important feature, or it has improved the shortcomings of the current API. Suppose we want to use 65536 or larger units, which is impossible in 16-bit Windows. Of course, in Win32, the function is defined as acceptable 32-bit parameters, so the scheduling of the scroll bar is very large.

When the program receives the WM_VSCROLL and WM_HSCROLL messages containing the SB_THUMBTRACK, SB_THUMBPSITION notification code, only 16-bit data is provided to indicate the current location of the scroll box. The real 32-bit value can be obtained by getScrollInfo () functions.

SetscrollInfo () and getScrollInfo () syntax is

Setscrollinfo (HWND, IBAR, & Si, BREDRAW); GetScrollInfo (HWND, IBAR, & SI);

Like other rolling strip functions, the parameters of the IBAR are SB_VERT OR SB_HORZ, which may also be SB_CTL for scroll bar control. Setscrollinfo () The last parameter can be true or false, pointing to whether to re-draw the scroll bar after the new information is required to re-draw.

The third parameter of the two functions is the ScrollInfo structure, which is defined as:

TypedEf struct tagscrollinfo {uint cbsize; // sizeof (scrollinfo) uint fmask; // parameter option int nmin; // scroll bar range minimum int nmax; // Scroll strip range maximum uint npage; // page size int NPOS; // Scroll box Current position int NTRACKPOS; //si.cbmask Set to SIF_TRACKPOS, scroll box current position} scrollinfo, * pscrollinfo; CBSIZE field must be set to the ScrollInfo structure before calling setscrollInfo ():

Si.cbsize = sizeof (si);

or

Si.cbsize = sizeof (scrollInfo);

After gradually familiar with Windows, we will find that several structures are also like this ScrollInfo structure, and the first domain indicates the size of the structure. This field enables future Windows versions to expand structures and add new features, and is still compatible with previously compiled versions.

Set the Fmask domain to one or more flags starting with the SIF prefix. When using SIF_RANGE via setscrollinfo (), the NMIN and NMAX domain must be set to the desired scroll bar range. The function returns the range of the scroll bar when using SIF_RANGE via getScrollInfo ().

When setscrollinfo () uses the SIF_POS flag, the function is used to set the position of the scroll bar. When using this flag by getScrollInfo (), the function will return the current location of the scroll bar.

When setscrollinfo () uses the SIF_PAGE flag, the function is used to set the page size. When using this flag by getScrollInfo (), the function will get the size of the current page.

When processed with SB_THUMBTRACK, SBTHUMBPOSITION notification code, only the SIF_TRACKPOS flag is used by getScrollInfo (), and the NTrackPos domain will indicate the current 32-bit scroll position.

The SIF_ALL flag is a combination of SIF_RANGE, SIF_POS, SIF_PAGE, SIF_TRACKPOS. This is convenient when setting scroll bar parameters during the WM_SIZE message.

The scroll range setting in the sysmets2 program is set to 0, and the maximum is Numlines-1. When the scroll bar position is 0, the first row information is displayed on top of the client area. When the position of the scroll bar is Numlines-1, the last row is displayed on the top of the client area and does not see other rows.

The SYSMETS2 scrolling range is too big, in fact, it is only necessary to display the last line of information at the bottom of the client area, and don't display the last line to the top. We can make some modifications to Sysmets2 to achieve this. When processed the WM_CREATE message, the scroll bar range is not set, but wait until the WM_SIZE message is received, then do it again:

Ivscrollmax = max (0, Numlines-cyclient / cychar); setscrollRange (hwnd, sb_vert, 0, ivscrollmax, true);

Numlines-cyclient / cychar, this is the key. It is assumed that Numline is equal to 75 (i.e., the rolling strips ranges from 0 to 74), and assumes that the specific window size is 50 (Cyclient divides cychar). That is to say, we have 75 lines of information, but only 50 lines can be displayed in the client area at a time. In this case, there are 25 lines that we can't see. You must scroll 25 units when we want to see the last line of information. At this time, 25 line information will appear on top of the client area, and 74 line information is displayed at the bottom of the client area. Use the above two lines of code to set the range to 0, and the maximum 25. When the scroll bar position is equal to 0, the program displays 0 to 49 lines. When the rolling bar position is equal to 1, the program displays 1 to 50 lines, when the scroll bar position is equal to 25, the program displays 25 to 74 line information. Si.cbsize = sizeof (scrollinfo); si.cbmask = sif_range | sif_page; si.nmin = 0; si.nmax = Numlines - 1; si.npage = cyclient / cychar;

SetscrollInfo (HWND, SB_VERT, & SI, TRUE);

At this time, Windows will limit the maximum rolling stripe range as

Si.nmax - Si.NPAGE 1

Not Numlines-1. This is very convenient. As mentioned earlier, it is assumed that Numlines is equal to 75, then the maximum range of the last scroll bar is 74-50 1, which is 25. This is exactly what we want. These are all automatic settings. Although Si.NMAX is set to Numlines-1 in the code above, the system will automatically set it to Si.NMAX - Si.NPage 1. There are many obvious translation errors in the textbook, so I don't know if my understanding is right. This broop! Nor did you have any errata. If the translation in the book is correct, what I said above is correct. If this book is Hou SIR translation, there will be an errata.

I have sent a bunch of complaints, but I can only blame myself. I have a last program of the fourth chapter sysmets3.

Winmain () section, the third parameter of CREATEWINDOW () becomes

WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL

The WM_CREATE section is nothing wrong with the previous program, just one more

IMAXWIDTH = 40 * cxchar 22 * ​​cxcaps;

This is the maximum width of the customer area. It is prepared for horizontal scroll bar.

WM_SIZE section

CxClient = loword (LPARAM); cyclient = HiWord (LPARAM);

In order to determine the page size, the customer area size is obtained first. Next, set the rolling range and the page size of the vertical scroll bar.

Si.cbsize = sizeof (si); si.fmask = SIF_RANGE | SIF_PAGE; Si.nmin = 0; Si.NMAX = Numlines-1; Si.NPage = cyclient / cychar; setscrollinfo (hwnd, sb_vert, & si, true);

Below is a rolling range and the page size set the horizontal scroll bar.

Si.cbsize = sizeof (si); si.fmask = SIF_RANGE | SIF_PAGE; Si.NMIN = 0; Si.NMAX = 2 imaxwidth / cxchar; si.npage = cxclient / cxchar; setscrollinfo (hwnd, sb_horz, & si, true );

As mentioned earlier, although we set the maximum scrolling range to 'Numlines-1' and '2 ImaxWidth / CxChar', Windows automatically changes these two values: Numlines-1 - cyclient / cychar 1

with

2 iMaxwidth / cxchar - cxclient / cxchar 1

This way, for the vertical scroll bar, when the user drags the scroll box to the bottom, the last line always appears at the bottom of the client area, and the same truth is also the horizontal scroll bar, but because iMaxWidth / CxChar has a 2, So when the user pulls the horizontal scroll bar to the far right, there is two spaces between the client zone and the last column.

The WM_VSCROLL message section, which processes the vertical scroll bar message. First use getScrollInfo () to get information on the scroll bar,

Si.cbsize = sizeof (si); si.fmask = Sif_all; GetScrollInfo (HWND, SB_VERT, & SI);

Then the Switch judgment is part, this is well understood, and the corresponding response is made according to the specific operation, and the results are saved into Si.pos. Finally, set the position of the scroll bar to Si.pos using setscrollinfo ().

There is one before the Switch statement

IVERTPOS = si.pos;

The program uses IVERTPOS to save the value before the Si.pos changes.

IF (Si.NPOS! = IVERTPOS)

After the Switch statement, if the value of Si.npos has changed, the condition of the IF statement above is True, and then executes

ScrollWindow (hwnd, 0, cychar * (ivertpos-si.npos), null, null; UpdateWindow (hwnd);

The function of scrollwindow () is to scroll through the customer area content. Assume that the scroll bar receives SB_LINEDOWN, Si.npos will be bigger than IVertPOS, that is,

IVertpos - Si.npos

The value is -1,

At this time, scrollWindow () will move the contents of the customer area up. When the third parameter of ScrollWindow () is positive, the function will move the content of the client area. When I talked about the scroll, I said that when we drop the scroll bar, the content of the customer area was moved up, and you must pay attention to this.

UpdateWindow () makes it immediately refreshed.

The horizontal scroll bar portion is also the same.

WM_PAINT section,

Save the current position of the vertical scroll bar and the horizontal scroll bar to IVertPOS and IHORZPOS.

Now suppose, a total of 75 lines of information (0 lines to 74 lines) need to be displayed, and 50 rows can be displayed (0 lines to 49 lines). The original position of the scroll bar is 0.

The user moved the scroll bar down, that is, the information of the customer area should move two lines, this time the 0th line, the first line has disappeared, and the top of the client area shows the information of the second line. And originally shown on the 49th line of the last line of the client area to Chapter 47. At this time, Chapter 48, the 49th line became a blank area

ps.rcpaint.top

It is the upper left corner coordinate of the blank area.

ps.rcpaint.top/cychar

It became the number of rows in the upper line of the blank area, followed by the above assumption, this is the 48th line. Two rows are moved over the customer zone, so the content of the 50th line is displayed at the position of the 48 line. Then shown in line 49 is the content of the 51st line. Now the customer area shows

Chapter 2 ~~~~~~ 51

Content.

ps.rcpaint.bottom / cychar

It is the display position of the last line of the blank area.

ipaintbeg = max (0, Ivertpos ps.rcpaint.top / cychar); ipaintend = min (Numlines - 1, IVERTPOS PS.RCPAINT.BOTTOM / CYCHAR); but we can see

ps.rcpaint.top / cychar

What is IVERTPOS in front? Why is this?

Although it is a line 48, the content to be displayed is the original row. On the 48th line, the contents of the 50th line are displayed, so add the number of lines of moving lines IVERTPOS, where IVERTPOS is 2, so it is only possible to display 50 rows on line 48.

Enter for loop:

At this time, the value of iPaintBeg is 50, and the value of ipaintend is 52.

Y = cychar * (i-ingtepos);

The value of y becomes 48, the display position of the 50th line information is 48,

Then use textOut () to display text strings.

Textout (HDC, X, Y, Sysmetrics [i] .szlabel, Lstrlen (sysmetrics [i] .szlabel);

To display the contents of the first line, it is the content of the 50th line, the display coordinate y is the coordinates of the 48th line, so the program displays the contents of the 50th line to the 48th line to push.

A method of speeding up WM_PAINT is demonstrated by the Sysmets3, and the WM_Paint code determines the row in the invalid area and only retrays these rows. The code is complicated but the speed is fast.

转载请注明原文地址:https://www.9cbs.com/read-27626.html

New Post(0)