Little confusion

Hi there, i started Windows programming with Windows 5th by Charles Petzold, in his little example "CHECKER4.C", he processes WM_SETFOCUS by calling

SetFocus (GetDlgItem (hwnd, idFocus));

thus setting the input focus to one of the child windows which child ID is idFocus. ChildWndProc processes WM_SETFOCUS by saving the child ID receiving the input focus in the global variable idFocus

idFocus = GetWindowLong (hwnd, GWL_ID) ;

Does it makes sense to set the "idFocus" again, i mean in the SetFocus() function, idFocus is already the child ID of the child window which is supposed to receive WM_SETFOCUS. If i didnt misunderstand.
Here are the procedures:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static HWND hwndChild[DIVISIONS][DIVISIONS] ;
     int         cxBlock, cyBlock, x, y ;
     
     switch (message)
     {
     case WM_CREATE :
          for (x = 0 ; x < DIVISIONS ; x++)
               for (y = 0 ; y < DIVISIONS ; y++)
                    hwndChild[x][y] = CreateWindow (szChildClass, NULL,
                              WS_CHILDWINDOW | WS_VISIBLE,
                              0, 0, 0, 0,
                              hwnd, (HMENU) (y << 8 | x),
                              (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
                              NULL) ;
          return 0 ;
               
     case WM_SIZE :
          cxBlock = LOWORD (lParam) / DIVISIONS ;
          cyBlock = HIWORD (lParam) / DIVISIONS ;
          
          for (x = 0 ; x < DIVISIONS ; x++)
                for (y = 0 ; y < DIVISIONS ; y++)
                    MoveWindow (hwndChild[x][y],
                                x * cxBlock, y * cyBlock,
                                cxBlock, cyBlock, TRUE) ;
          return 0 ;
                       
     case WM_LBUTTONDOWN :
          MessageBeep (0) ;
          return 0 ;

          // On set-focus message, set focus to child window

     case WM_SETFOCUS:
          SetFocus (GetDlgItem (hwnd, idFocus)) ;
          return 0 ;

          // On key-down message, possibly change the focus window

     case WM_KEYDOWN:
          x = idFocus & 0xFF ;
          y = idFocus >> 8 ;

          switch (wParam)
          {
          case VK_UP:    y-- ;                    break ;
          case VK_DOWN:  y++ ;                    break ;
          case VK_LEFT:  x-- ;                    break ;
          case VK_RIGHT: x++ ;                    break ;
          case VK_HOME:  x = y = 0 ;              break ;
          case VK_END:   x = y = DIVISIONS - 1 ;  break ;
          default:       return 0 ;
          }

          x = (x + DIVISIONS) % DIVISIONS ;
          y = (y + DIVISIONS) % DIVISIONS ;

          idFocus = y << 8 | x ;

          SetFocus (GetDlgItem (hwnd, idFocus)) ;
          return 0 ;

     case WM_DESTROY :
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT message, 
                               WPARAM wParam, LPARAM lParam)
{
     HDC         hdc ;
     PAINTSTRUCT ps ;
     RECT        rect ;
     
     switch (message)
     {
     case WM_CREATE :
          SetWindowLong (hwnd, 0, 0) ;       // on/off flag
          return 0 ;

     case WM_KEYDOWN:
               // Send most key presses to the parent window
          
          if (wParam != VK_RETURN && wParam != VK_SPACE)
          {
               SendMessage (GetParent (hwnd), message, wParam, lParam) ;
               return 0 ;
          }
               // For Return and Space, fall through to toggle the square
          
     case WM_LBUTTONDOWN :
          SetWindowLong (hwnd, 0, 1 ^ GetWindowLong (hwnd, 0)) ;
          SetFocus (hwnd) ;
          InvalidateRect (hwnd, NULL, FALSE) ;
          return 0 ;

               // For focus messages, invalidate the window for repaint
          
     case WM_SETFOCUS:
          idFocus = GetWindowLong (hwnd, GWL_ID) ;

               // Fall through

     case WM_KILLFOCUS:
          InvalidateRect (hwnd, NULL, TRUE) ;
          return 0 ;
          
     case WM_PAINT :
          hdc = BeginPaint (hwnd, &ps) ;
          
          GetClientRect (hwnd, &rect) ;
          Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;

               // Draw the "x" mark
          
          if (GetWindowLong (hwnd, 0))
          {
               MoveToEx (hdc, 0,          0, NULL) ;
               LineTo   (hdc, rect.right, rect.bottom) ;
               MoveToEx (hdc, 0,          rect.bottom, NULL) ;
               LineTo   (hdc, rect.right, 0) ;
          }

               // Draw the "focus" rectangle
          
          if (hwnd == GetFocus ())
          {
               rect.left   += rect.right / 10 ;
               rect.right  -= rect.left ;
               rect.top    += rect.bottom / 10 ;
               rect.bottom -= rect.top ;

               SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
               SelectObject (hdc, CreatePen (PS_DASH, 0, 0)) ;
               Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom) ;
               DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ;
          }

          EndPaint (hwnd, &ps) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}
Its been a long time since I looked at these programs, but it appears to me that the main program window (the one that contains all the smaller child windows) has a title bar, and focus could be set to an inactive instance of the program by just clicking the inactive title bar. In that case, no particular cell would have focus. However, the global variable you mentioned would likely have a child window id in it, to which the code shown would set the focus to. Does that make sense?
Got that|
But why set idFocus twice with the same value.
Last edited on
You'll have to be more specific and show me exactly where idFocus is being set twice. In the code you've posted, I only see it being set once.
In the WndProc, the function:
SetFocus (GetDlgItem (hwnd, idFocus)) ;
sets the input focus to the child window which ID is idFocus, this cause Windows send WM_SETFOCUS to that child window, right? The idFocus doesnt be changed, it still refer to the child window mentioned above. and in the ChildWndProc:
1
2
case WM_SETFOCUS:
          idFocus = GetWindowLong (hwnd, GWL_ID) ;

it sets the idFocus to the same value. ( the child window ID)

Sorry for my bad EL =))
Last edited on
Topic archived. No new replies allowed.