[读书笔记]Windows程序设计(第5版)
2022-12-15 22:2:0 Author: bbs.pediy.com(查看原文) 阅读量:12 收藏

[读书笔记]Windows程序设计(第5版)

2022-12-15 22:02 3722

目录

一、起步

1.1.第一个Windows程序

HelloMsg.c

1

2

3

4

5

6

7

8

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

{

    MessageBox(NULL,TEXT("Hello,Windows 98!"), TEXT("HelloMsg"), 0);

    return 0;

}

说明:

  • WINAPI:#define WINAPI __stdcall
  • 第一个参数:实例句柄
  • 第二个参数:通常总是为NULL(定义为0)
  • 第三个参数:用来运行程序的命令行
  • 第四个参数:用来指明程序最初如何显示:正常显示或最大化到全屏

1.2.MessageBox函数

说明:

  • 第一个参数:通常是一个窗口句柄
  • 第二个参数:信息框的内容
  • 第三个参数:标题栏的内容
  • 第四个参数:按钮类型

二、Unicode简介

2.1.宽字符和C语言

char数据类型

1

2

3

char c = 'A';            //1个字节  0x41

char * p;                //4个字节

char a[] = "Hello!"        //7个字节

宽字符

1

2

3

4

5

6

//typedef unsigned short wchar_t

wchar_t c = 'A';            //2个字节  0x0041

wchar_t * p;                //4个字节

wchar_t a[] = L"Hello!"        //14个字节

三、窗口与消息

3.1.HELLOWIN程序

HelloWin.c

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("HelloWin");

    HWND hwnd;

    MSG msg;

    WNDCLASS wndclass;

    //水平尺寸和垂直尺寸

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    //WndProc窗口类的窗口过程函数:处理传递给所有基于该窗口类创建的窗口的所有消息

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    //应用程序的实例句柄

    wndclass.hInstance = hInstance;

    //加载图标

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    //加载鼠标光标

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    //指定背景色

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    //窗口类的菜单

    wndclass.lpszMenuName = NULL;

    //窗口类名称

    wndclass.lpszClassName = szAppName;

    //为应用程序的窗口注册一个窗口类

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("this program requires Windows NT!"),szAppName,MB_ICONERROR);

        return 0;

    }

    //基于窗口类创建一个窗口

    hwnd = CreateWindow(szAppName,  // 窗口类名称

        TEXT("The Hello Program"),  // 窗口标题

        WS_OVERLAPPEDWINDOW,        // 窗口风格

        CW_USEDEFAULT,              // 初始x坐标

        CW_USEDEFAULT,              // 初始y坐标

        CW_USEDEFAULT,              // 初始x方向尺寸

        CW_USEDEFAULT,              // 初始y方向尺寸

        NULL,                       // 父窗口句柄

        NULL,                       // 窗口菜单句柄

        hInstance,                  // 程序实例句柄

        NULL);                      // 创建参数

    //在屏幕中显示窗口

    ShowWindow(hwnd, iCmdShow);

    //指示窗口对其自身进行重绘

    UpdateWindow(hwnd);

    //从消息队里获取消息

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);      //翻译一些键盘消息

        DispatchMessage(&msg);        //将消息发送给窗口过程

    }

    return msg.wParam;

}

//窗口过程函数

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    HDC hdc;

    PAINTSTRUCT ps;

    RECT rect;

    switch (message)

    {

    case WM_CREATE:

        //播放声音文件

        PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);

        return 0;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);    //表明窗口绘制开始

        GetClientRect(hwnd, &rect);        //获取窗口客户区的尺寸

        //显示一个文本字符串

        DrawText(hdc, TEXT("Hello, Windows 98!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

        //结束窗口绘制

        EndPaint(hwnd, &ps);

        return 0;

    case WM_DESTROY:

        //将“退出”消息插入消息队列

        PostQuitMessage(0);

        return 0;

    }

    //执行默认的消息处理

    return DefWindowProc(hwnd, message, wParam, lParam);

}

3.2.通盘考虑

1.大写标识符

标识符其实都是数值常量,前缀表明常量所属的一般类别

前缀 常量
CS 类风格选项
CW 创建窗口选项
DT 文本绘制选项
IDI 图标的ID号
IDC 光标的ID号
MB 消息框选项
SND 声音选项
WM 窗口消息
WS 窗口风格

2.新数据类型

  • WPARAM:等价于UINT
  • LPARAM:等价于LONG
  • LRESULT:等价于LONG

3.四种数据结构

结构 含义
MSG 消息结构
WNDCLASS 窗口类结构
PAINTSTRUCT 绘制结构
RECT 矩形结构

4.理解句柄

标识符 含义
HINSTANCE 实例句柄---程序本身
HWND 窗口句柄
HDC 设备环境句柄

5.匈牙利标记法

即变量名以表明该变量数据类型的小写字母开始,例如

  • szCmdline的前缀sz表示“以零结束的字符串”
  • hInstance的前缀h表示“句柄”
  • iCmdShow的前缀i表示“整型”

变量名前缀如下

前缀 数据类型
c char或 WCHAR 或 TCHAR
by byte
n short
i int
x,y int,表示x坐标和y坐标
cx,cy int, 表示x或y的长度, c表示count(计数)
b或f BOOL(int):f表示flag
w WORD(无符号短整数)
l LONG(长整数)
dw DWORD(无符号长整数)
fn 函数
s 字符串
sz 以零结束的字符串
h 句柄
p 指针

四、文本输出

4.1.获取设备环境

获取设备环境方法1:BeginPain和EndPaint函数

将原来的无效区域有效化

1

2

3

WINUSERAPI HDC WINAPI BeginPaint(

    _In_ HWND hWnd,

    _Out_ LPPAINTSTRUCT lpPaint);

两个参数

  • 参数1:窗口的句柄
  • 参数2:是一个类型位PAINTSTRUCT结构的变量的地址

获取设备环境方法2:GetDC

与从BeginPaint函数返回的设备句柄不同,从GetDC返回的设备句柄中的裁剪区域是整个客户区,而不仅仅

是在无效矩形里

1

2

3

hdc = GetDC(hwnd);

ReleaseDC(hwnd, hdc);

4.2.TEXTOUT函数详解

1

TextOut(hdc, x, y, psText, iLength);

说明:

  • hdc:设备环境句柄,决定文本显示的特性
  • x:相对于客户区的左上角。从左往右增大
  • y:相对于客户区的左上角。从上往下增大
  • psText:指向字符串的指针
  • iLength:字符串的长度

4.3.字符大小

通过调用GetSystemMetrics函数来获取用户界面的尺寸。

通过调用GetTextMetrics函数,可以获取字体尺寸。GetTextMetrics函数需要一个设备环境句柄,因为它会返回该设备环境当前选定的字体的信息。windows将把字符尺寸的各种值复制到类型为TEXTMETRIC的结构中。

该结构体共有20个字段,我们仅关心其中的前7个字段

1

2

3

4

5

6

7

8

9

10

11

12

13

typedef struct tagTEXTMETRICW

{

    LONG        tmHeight;

    LONG        tmAscent;

    LONG        tmDescent;

    LONG        tmInternalLeading;

    LONG        tmExternalLeading;

    LONG        tmAveCharWidth;

    LONG        tmMaxCharWidth;

    .

    .

    .

} TEXTMETRICW, *PTEXTMETRICW, NEAR *NPTEXTMETRICW, FAR *LPTEXTMETRICW;

  • tmHeight:它是tmAscent和tmDescent的和。这两个值分别是字符在基线之上和之下的最大高度。

  • tmInternalLeading(内部间距):包含在tmAscent中(也就是包含在tmHeight中),tmInternalLeading可以设置为0

  • tmExternalLeading:不包含在tmHeight的值里,这个值在本书中使用的系统字体通常为0

  • tmAveCharWidth和tmMaxCharWidth两个字段描述了字符的宽度,tmAveCharWidth是小写字符的加权平均宽度。tmMaxCharWidth是字体中最宽的字符的宽度。在等宽字体中,这两个值是一样的。在变宽字体中tmMaxCharWidth是tmAveCharWidth的1.5倍。

4.4.滚动条

GetScrollInfo

1

2

3

4

WINUSERAPI BOOL WINAPI GetScrollInfo(

    _In_ HWND hwnd,

    _In_ int nBar,

    _Inout_ LPSCROLLINFO lpsi);

SetScrollInfo

1

2

3

4

5

WINUSERAPI int WINAPI SetScrollInfo(

    _In_ HWND hwnd,

    _In_ int nBar,

    _In_ LPCSCROLLINFO lpsi,

    _In_ BOOL redraw);

  • 参数1:窗口句柄
  • 参数2:SB_VERT或 SB_HORZ
  • 参数4:可以是TRUE或FALSE,表示是否希望windows根据新的消息重绘滚动条

参数3是一个SCROLLINFO结构体

1

2

3

4

5

6

7

8

9

10

11

typedef struct tagSCROLLINFO

{

    UINT    cbSize;   //设为sizeof(SCROLLINFO)

    UINT    fMask;      //要设置或获取的值

    int     nMin;     //范围的最小值

    int     nMax;     //范围的最大值

    UINT    nPage;    //页面大小

    int     nPos;     //当前位置

    int     nTrackPos;  //当前追踪位置

}   SCROLLINFO, FAR *LPSCROLLINFO;

typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;

4.5.综合使用

SysMets3.h

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

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

/*-----------------------------------------------

   SYSMETS.H -- System metrics display structure

  -----------------------------------------------*/

struct

{

    int     iIndex;

    TCHAR* szLabel;

    TCHAR* szDesc;

}

sysmetrics[] =

{

     SM_CXSCREEN,             TEXT("SM_CXSCREEN"),

                              TEXT("Screen width in pixels"),

     SM_CYSCREEN,             TEXT("SM_CYSCREEN"),

                              TEXT("Screen height in pixels"),

     SM_CXVSCROLL,            TEXT("SM_CXVSCROLL"),

                              TEXT("Vertical scroll width"),

     SM_CYHSCROLL,            TEXT("SM_CYHSCROLL"),

                              TEXT("Horizontal scroll height"),

     SM_CYCAPTION,            TEXT("SM_CYCAPTION"),

                              TEXT("Caption bar height"),

     SM_CXBORDER,             TEXT("SM_CXBORDER"),

                              TEXT("Window border width"),

     SM_CYBORDER,             TEXT("SM_CYBORDER"),

                              TEXT("Window border height"),

     SM_CXFIXEDFRAME,         TEXT("SM_CXFIXEDFRAME"),

                              TEXT("Dialog window frame width"),

     SM_CYFIXEDFRAME,         TEXT("SM_CYFIXEDFRAME"),

                              TEXT("Dialog window frame height"),

     SM_CYVTHUMB,             TEXT("SM_CYVTHUMB"),

                              TEXT("Vertical scroll thumb height"),

     SM_CXHTHUMB,             TEXT("SM_CXHTHUMB"),

                              TEXT("Horizontal scroll thumb width"),

     SM_CXICON,               TEXT("SM_CXICON"),

                              TEXT("Icon width"),

     SM_CYICON,               TEXT("SM_CYICON"),

                              TEXT("Icon height"),

     SM_CXCURSOR,             TEXT("SM_CXCURSOR"),

                              TEXT("Cursor width"),

     SM_CYCURSOR,             TEXT("SM_CYCURSOR"),

                              TEXT("Cursor height"),

     SM_CYMENU,               TEXT("SM_CYMENU"),

                              TEXT("Menu bar height"),

     SM_CXFULLSCREEN,         TEXT("SM_CXFULLSCREEN"),

                              TEXT("Full screen client area width"),

     SM_CYFULLSCREEN,         TEXT("SM_CYFULLSCREEN"),

                              TEXT("Full screen client area height"),

     SM_CYKANJIWINDOW,        TEXT("SM_CYKANJIWINDOW"),

                              TEXT("Kanji window height"),

     SM_MOUSEPRESENT,         TEXT("SM_MOUSEPRESENT"),

                              TEXT("Mouse present flag"),

     SM_CYVSCROLL,            TEXT("SM_CYVSCROLL"),

                              TEXT("Vertical scroll arrow height"),

     SM_CXHSCROLL,            TEXT("SM_CXHSCROLL"),

                              TEXT("Horizontal scroll arrow width"),

     SM_DEBUG,                TEXT("SM_DEBUG"),

                              TEXT("Debug version flag"),

     SM_SWAPBUTTON,           TEXT("SM_SWAPBUTTON"),

                              TEXT("Mouse buttons swapped flag"),

     SM_CXMIN,                TEXT("SM_CXMIN"),

                              TEXT("Minimum window width"),

     SM_CYMIN,                TEXT("SM_CYMIN"),

                              TEXT("Minimum window height"),

     SM_CXSIZE,               TEXT("SM_CXSIZE"),

                              TEXT("Min/Max/Close button width"),

     SM_CYSIZE,               TEXT("SM_CYSIZE"),

                              TEXT("Min/Max/Close button height"),

     SM_CXSIZEFRAME,          TEXT("SM_CXSIZEFRAME"),

                              TEXT("Window sizing frame width"),

     SM_CYSIZEFRAME,          TEXT("SM_CYSIZEFRAME"),

                              TEXT("Window sizing frame height"),

     SM_CXMINTRACK,           TEXT("SM_CXMINTRACK"),

                              TEXT("Minimum window tracking width"),

     SM_CYMINTRACK,           TEXT("SM_CYMINTRACK"),

                              TEXT("Minimum window tracking height"),

     SM_CXDOUBLECLK,          TEXT("SM_CXDOUBLECLK"),

                              TEXT("Double click x tolerance"),

     SM_CYDOUBLECLK,          TEXT("SM_CYDOUBLECLK"),

                              TEXT("Double click y tolerance"),

     SM_CXICONSPACING,        TEXT("SM_CXICONSPACING"),

                              TEXT("Horizontal icon spacing"),

     SM_CYICONSPACING,        TEXT("SM_CYICONSPACING"),

                              TEXT("Vertical icon spacing"),

     SM_MENUDROPALIGNMENT,    TEXT("SM_MENUDROPALIGNMENT"),

                              TEXT("Left or right menu drop"),

     SM_PENWINDOWS,           TEXT("SM_PENWINDOWS"),

                              TEXT("Pen extensions installed"),

     SM_DBCSENABLED,          TEXT("SM_DBCSENABLED"),

                              TEXT("Double-Byte Char Set enabled"),

     SM_CMOUSEBUTTONS,        TEXT("SM_CMOUSEBUTTONS"),

                              TEXT("Number of mouse buttons"),

     SM_SECURE,               TEXT("SM_SECURE"),

                              TEXT("Security present flag"),

     SM_CXEDGE,               TEXT("SM_CXEDGE"),

                              TEXT("3-D border width"),

     SM_CYEDGE,               TEXT("SM_CYEDGE"),

                              TEXT("3-D border height"),

     SM_CXMINSPACING,         TEXT("SM_CXMINSPACING"),

                              TEXT("Minimized window spacing width"),

     SM_CYMINSPACING,         TEXT("SM_CYMINSPACING"),

                              TEXT("Minimized window spacing height"),

     SM_CXSMICON,             TEXT("SM_CXSMICON"),

                              TEXT("Small icon width"),

     SM_CYSMICON,             TEXT("SM_CYSMICON"),

                              TEXT("Small icon height"),

     SM_CYSMCAPTION,          TEXT("SM_CYSMCAPTION"),

                              TEXT("Small caption height"),

     SM_CXSMSIZE,             TEXT("SM_CXSMSIZE"),

                              TEXT("Small caption button width"),

     SM_CYSMSIZE,             TEXT("SM_CYSMSIZE"),

                              TEXT("Small caption button height"),

     SM_CXMENUSIZE,           TEXT("SM_CXMENUSIZE"),

                              TEXT("Menu bar button width"),

     SM_CYMENUSIZE,           TEXT("SM_CYMENUSIZE"),

                              TEXT("Menu bar button height"),

     SM_ARRANGE,              TEXT("SM_ARRANGE"),

                              TEXT("How minimized windows arranged"),

     SM_CXMINIMIZED,          TEXT("SM_CXMINIMIZED"),

                              TEXT("Minimized window width"),

     SM_CYMINIMIZED,          TEXT("SM_CYMINIMIZED"),

                              TEXT("Minimized window height"),

     SM_CXMAXTRACK,           TEXT("SM_CXMAXTRACK"),

                              TEXT("Maximum draggable width"),

     SM_CYMAXTRACK,           TEXT("SM_CYMAXTRACK"),

                              TEXT("Maximum draggable height"),

     SM_CXMAXIMIZED,          TEXT("SM_CXMAXIMIZED"),

                              TEXT("Width of maximized window"),

     SM_CYMAXIMIZED,          TEXT("SM_CYMAXIMIZED"),

                              TEXT("Height of maximized window"),

     SM_NETWORK,              TEXT("SM_NETWORK"),

                              TEXT("Network present flag"),

     SM_CLEANBOOT,            TEXT("SM_CLEANBOOT"),

                              TEXT("How system was booted"),

     SM_CXDRAG,               TEXT("SM_CXDRAG"),

                              TEXT("Avoid drag x tolerance"),

     SM_CYDRAG,               TEXT("SM_CYDRAG"),

                              TEXT("Avoid drag y tolerance"),

     SM_SHOWSOUNDS,           TEXT("SM_SHOWSOUNDS"),

                              TEXT("Present sounds visually"),

     SM_CXMENUCHECK,          TEXT("SM_CXMENUCHECK"),

                              TEXT("Menu check-mark width"),

     SM_CYMENUCHECK,          TEXT("SM_CYMENUCHECK"),

                              TEXT("Menu check-mark height"),

     SM_SLOWMACHINE,          TEXT("SM_SLOWMACHINE"),

                              TEXT("Slow processor flag"),

     SM_MIDEASTENABLED,       TEXT("SM_MIDEASTENABLED"),

                              TEXT("Hebrew and Arabic enabled flag"),

     SM_MOUSEWHEELPRESENT,    TEXT("SM_MOUSEWHEELPRESENT"),

                              TEXT("Mouse wheel present flag"),

     SM_XVIRTUALSCREEN,       TEXT("SM_XVIRTUALSCREEN"),

                              TEXT("Virtual screen x origin"),

     SM_YVIRTUALSCREEN,       TEXT("SM_YVIRTUALSCREEN"),

                              TEXT("Virtual screen y origin"),

     SM_CXVIRTUALSCREEN,      TEXT("SM_CXVIRTUALSCREEN"),

                              TEXT("Virtual screen width"),

     SM_CYVIRTUALSCREEN,      TEXT("SM_CYVIRTUALSCREEN"),

                              TEXT("Virtual screen height"),

     SM_CMONITORS,            TEXT("SM_CMONITORS"),

                              TEXT("Number of monitors"),

     SM_SAMEDISPLAYFORMAT,    TEXT("SM_SAMEDISPLAYFORMAT"),

                              TEXT("Same color format flag")

};

SysMets3.c

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

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("SysMets3");

    HWND         hwnd;

    MSG          msg;

    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = NULL;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("Program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName,

        TEXT("Get System Metrics No. 3"),

        WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,   //添加水平和垂直滚动条

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static int  cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth;

    HDC         hdc;

    int         i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd;

    PAINTSTRUCT ps;

    SCROLLINFO  si;

    TCHAR       szBuffer[10];

    TEXTMETRIC  tm;

    switch (message)

    {

    case WM_CREATE:

        //获取窗口的设备环境句柄

        hdc = GetDC(hwnd);

        //获取默认系统字体的尺寸

        GetTextMetrics(hdc, &tm);

        //获取平均字符宽度

        cxChar = tm.tmAveCharWidth;

        //tmPitchAndFamily字段的低位决定字体是否为等宽字体:1表示变宽字体,0表示等宽字体

        //大写字符的平均宽度。在等宽字体中,cxCaps = cyChar。在变宽字体中,cxCaps = cyChar * 1.5

        cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;

        //获取字符的总高度

        cyChar = tm.tmHeight + tm.tmExternalLeading;

        //释放窗口的设备环境句柄

        ReleaseDC(hwnd, hdc);

        // 保存三列的总宽度

        iMaxWidth = 40 * cxChar + 22 * cxCaps;

        return 0;

    //窗口大小发生变化时

    case WM_SIZE:

        //lParam变量的低位是客户区的宽度

        cxClient = LOWORD(lParam); 

        //lParam变量的高位是客户区的高度

        cyClient = HIWORD(lParam);

        // Set vertical scroll bar range and page size

        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);

        // Set horizontal scroll bar range and page size

        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);

        return 0;

    //垂直滚动

    case WM_VSCROLL:

        // Get all the vertial scroll bar information

        si.cbSize = sizeof(si);

        si.fMask = SIF_ALL;

        GetScrollInfo(hwnd, SB_VERT, &si);

        // Save the position for comparison later on

        iVertPos = si.nPos;

        //wParam参数的低位代表鼠标在滚动条上的动作,这个值被称为“通知码”

        switch (LOWORD(wParam))

        {

        case SB_TOP:

            si.nPos = si.nMin;

            break;

        case SB_BOTTOM:

            si.nPos = si.nMax;

            break;

        case SB_LINEUP:

            si.nPos -= 1;

            break;

        case SB_LINEDOWN:

            si.nPos += 1;

            break;

        case SB_PAGEUP:

            si.nPos -= si.nPage;

            break;

        case SB_PAGEDOWN:

            si.nPos += si.nPage;

            break;

        //SB_THUMBTRACK通知码:当用户拖动滚动条的滑块时,程序会相应的滚动窗口的内容

        case SB_THUMBTRACK:

            //返回当前滑块的位置

            si.nPos = si.nTrackPos;

            break;

        default:

            break;

        }

        // Set the position and then retrieve it.  Due to adjustments

        //   by Windows it may not be the same as the value set.

        si.fMask = SIF_POS;

        SetScrollInfo(hwnd, SB_VERT, &si, TRUE);

        GetScrollInfo(hwnd, SB_VERT, &si);

        // If the position has changed, scroll the window and update it

        if (si.nPos != iVertPos)

        {

            ScrollWindow(hwnd, 0, cyChar * (iVertPos - si.nPos),

                NULL, NULL);

            UpdateWindow(hwnd);

        }

        return 0;

    //水平滚动

    case WM_HSCROLL:

        // Get all the vertial scroll bar information

        si.cbSize = sizeof(si);

        si.fMask = SIF_ALL;

        // Save the position for comparison later on

        GetScrollInfo(hwnd, SB_HORZ, &si);

        iHorzPos = si.nPos;

        switch (LOWORD(wParam))

        {

        case SB_LINELEFT:

            si.nPos -= 1;

            break;

        case SB_LINERIGHT:

            si.nPos += 1;

            break;

        case SB_PAGELEFT:

            si.nPos -= si.nPage;

            break;

        case SB_PAGERIGHT:

            si.nPos += si.nPage;

            break;

        //SB_THUMBPOSITION通知码:当用户拖动滚动条的滑块,程序只有在用户松开了鼠标键时才会滚动窗口的内容

        case SB_THUMBPOSITION:

            si.nPos = si.nTrackPos;      //返回当前滑块的位置

            break;

        default:

            break;

        }

        // Set the position and then retrieve it.  Due to adjustments

        //   by Windows it may not be the same as the value set.

        si.fMask = SIF_POS;

        SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);

        GetScrollInfo(hwnd, SB_HORZ, &si);

        // If the position has changed, scroll the window

        if (si.nPos != iHorzPos)

        {

            ScrollWindow(hwnd, cxChar * (iHorzPos - si.nPos), 0,

                NULL, NULL);

        }

        return 0;

    case WM_PAINT:

        //获取设备句柄

        hdc = BeginPaint(hwnd, &ps);

        // Get vertical scroll bar position

        si.cbSize = sizeof(si);

        si.fMask = SIF_POS;

        GetScrollInfo(hwnd, SB_VERT, &si);

        iVertPos = si.nPos;

        // Get horizontal scroll bar position

        GetScrollInfo(hwnd, SB_HORZ, &si);

        iHorzPos = si.nPos;

        // Find painting limits

        iPaintBeg = max(0, iVertPos + ps.rcPaint.top / cyChar);

        iPaintEnd = min(NUMLINES - 1,

            iVertPos + ps.rcPaint.bottom / cyChar);

        for (i = iPaintBeg; i <= iPaintEnd; i++)

        {

            x = cxChar * (1 - iHorzPos);

            y = cyChar * (i - iVertPos);

            TextOut(hdc, x, y,

                sysmetrics[i].szLabel,              //sysmetrics结构体的szLabel字段

                lstrlen(sysmetrics[i].szLabel));   //长度

            TextOut(hdc, x + 22 * cxCaps, y,

                sysmetrics[i].szDesc,

                lstrlen(sysmetrics[i].szDesc));

            SetTextAlign(hdc, TA_RIGHT | TA_TOP);    //设置为右上对齐

            TextOut(hdc, x + 22 * cxCaps + 40 * cxChar, y, szBuffer,

                wsprintf(szBuffer, TEXT("%5d"),

                    GetSystemMetrics(sysmetrics[i].iIndex)));

            SetTextAlign(hdc, TA_LEFT | TA_TOP);     //设置为默认左上对齐

        }

        EndPaint(hwnd, &ps);

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

五、绘图基础

5.1.获取设备环境句柄

1.在处理WM_PAINT消息时使用BeginPaint函数和EndPaint函数

1

2

3

hdc = BeginPaint(hwnd, &ps);   

    (other program lines)

EndPaint(hwnd, &ps);

ps是一个类型为PAINTSTRUCT的结构,PAINTSTRUCT结构还包含一个名为rcPaint的矩形结构,该结构定义了一个包围窗口客户区无效范围的矩形。使用BeginPaint函数获取的设备环境句柄,就只能在这个矩形内绘图,调用BeginPaint函数将使这个区域有效。

2.设备环境句柄还可以在处理非WM_PAINT消息时由windows程序获取

1

2

3

hdc = GetDC(hwnd);

    (other program lines)

ReleaseDC(hwnd, &hdc);

其中,设备环境句柄指的是窗口句柄为hwnd的窗口客户区,从GetDC函数返回的句柄可以在整个客户区绘制,并且GetDC和ReleaseDC函数并不使任何客户区的无效区域变为有效。

3、windows程序还可以获得用于整个窗口的,而不仅仅是窗口客户区的设备环境句柄

1

2

3

hdc = GetWindowDC(hwnd);

    (other program lines)

ReleaseDC(hwnd, &hdc);

这里的设备环境句柄除了包括客户区,还包含窗口标题栏、菜单、滚动条和客户区的外框。

5.2.获取设备环境信息

GetDeviceCaps可以获取设备的信息

DevCaps1.c

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

/*---------------------------------------------------------

   DEVCAPS1.C -- Device Capabilities Display Program No. 1

                 (c) Charles Petzold, 1998

  ---------------------------------------------------------*/

struct

{

    int     iIndex;

    TCHAR* szLabel;

    TCHAR* szDesc;

}

devcaps[] =

{

     HORZSIZE,      TEXT("HORZSIZE"),     TEXT("Width in millimeters:"),

     VERTSIZE,      TEXT("VERTSIZE"),     TEXT("Height in millimeters:"),

     HORZRES,       TEXT("HORZRES"),      TEXT("Width in pixels:"),

     VERTRES,       TEXT("VERTRES"),      TEXT("Height in raster lines:"),

     BITSPIXEL,     TEXT("BITSPIXEL"),    TEXT("Color bits per pixel:"),

     PLANES,        TEXT("PLANES"),       TEXT("Number of color planes:"),

     NUMBRUSHES,    TEXT("NUMBRUSHES"),   TEXT("Number of device brushes:"),

     NUMPENS,       TEXT("NUMPENS"),      TEXT("Number of device pens:"),

     NUMMARKERS,    TEXT("NUMMARKERS"),   TEXT("Number of device markers:"),

     NUMFONTS,      TEXT("NUMFONTS"),     TEXT("Number of device fonts:"),

     NUMCOLORS,     TEXT("NUMCOLORS"),    TEXT("Number of device colors:"),

     PDEVICESIZE,   TEXT("PDEVICESIZE"),  TEXT("Size of device structure:"),

     ASPECTX,       TEXT("ASPECTX"),      TEXT("Relative width of pixel:"),

     ASPECTY,       TEXT("ASPECTY"),      TEXT("Relative height of pixel:"),

     ASPECTXY,      TEXT("ASPECTXY"),     TEXT("Relative diagonal of pixel:"),

     LOGPIXELSX,    TEXT("LOGPIXELSX"),   TEXT("Horizontal dots per inch:"),

     LOGPIXELSY,    TEXT("LOGPIXELSY"),   TEXT("Vertical dots per inch:"),

     SIZEPALETTE,   TEXT("SIZEPALETTE"),  TEXT("Number of palette entries:"),

     NUMRESERVED,   TEXT("NUMRESERVED"),  TEXT("Reserved palette entries:"),

     COLORRES,      TEXT("COLORRES"),     TEXT("Actual color resolution:")

};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("DevCaps1");

    HWND         hwnd;

    MSG          msg;

    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = NULL;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName, TEXT("Device Capabilities"),

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static int  cxChar, cxCaps, cyChar;

    TCHAR       szBuffer[10];

    HDC         hdc;

    int         i;

    PAINTSTRUCT ps;

    TEXTMETRIC  tm;

    switch (message)

    {

    case WM_CREATE:

        hdc = GetDC(hwnd);

        GetTextMetrics(hdc, &tm);

        cxChar = tm.tmAveCharWidth;

        cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;

        cyChar = tm.tmHeight + tm.tmExternalLeading;

        ReleaseDC(hwnd, hdc);

        return 0;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        for (i = 0; i < NUMLINES; i++)

        {

            TextOut(hdc, 0, cyChar * i,

                devcaps[i].szLabel,

                lstrlen(devcaps[i].szLabel));

            TextOut(hdc, 14 * cxCaps, cyChar * i,

                devcaps[i].szDesc,

                lstrlen(devcaps[i].szDesc));

            SetTextAlign(hdc, TA_RIGHT | TA_TOP);

            TextOut(hdc, 14 * cxCaps + 35 * cxChar, cyChar * i, szBuffer,

                wsprintf(szBuffer, TEXT("%5d"),

                    GetDeviceCaps(hdc, devcaps[i].iIndex)));

            SetTextAlign(hdc, TA_LEFT | TA_TOP);

        }

        EndPaint(hwnd, &ps);

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

5.3.设定像素

SetPixel函数将坐标为x和y的像素点设定为某个特定的颜色

1

SetPixel(hdc,x, y, crColor);

最后一个参数是COLORREF类型,用来指定颜色

GetPixel函数返回指定坐标位置的像素的颜色

1

crColor = GetPixel(hdc,x,y);

5.4.直线

画一条直线,必须调用两个函数。第一个函数用来指定直线的起点,第二个函数用来指定直线的终点

1

2

3

MoveToEx(hdc, xBeg, yBeg, NULL);   //起点

LineTo(hdc, xEnd, yEnd);     //终点

获取当前位置

1

GetCurrentPositionEx(hdc, &pt);

将数组的点连接成线,调用Polyline函数划线会更加容易

1

Polyline(hdc, apt, 5);     //最后一个参数5表示点的个数

5.5.边框绘制函数

画矩形

1

Rectangle(hdc,xLeft, yTop, xRight, yBottom);   //左上角和右下角坐标

画椭圆

1

Ellipse(hdc,xLeft, yTop, xRight, yBottom);

5.6.创建、选择和删除画笔

1.创建画笔

1

hPen = CreatePen(iPenStyle, iWidth, crColor);

参数iPenStyle决定画笔绘制的是实线(PS_SOLID)或者虚线(PS_DASH)或者点线(PS_DOT)

参数iWidth表示画笔的宽度

参数crColor执定画笔的颜色

2.选择画笔

1

3.删除画笔

4.可以随时创建画笔,将CreatePen和SelectObject组合到一条语句中

将一支画笔选入到一个新创建的设备环境,保存SelectObject返回的画笔句柄

1

hPen = SelectObject(hdc, CreatePen(PS_DASH, 0, rgb(255,0,0)));

删除

1

DeleteObject(SelectObject(hdc, hPen));

六、键盘

6.1.击键消息

当用户按下一个键时,windows将WM_KEYDOWN或WM_SYSKEYDOWN消息放入具有输入焦点的窗口的消息队列中。

当该键被释放时,windows把WM_KEYUP或WM_SYSKEYUP消息放入相应的消息队列中。

键按下 键释放
非系统键击 WM_KEYDOWN WM_KEYUP
系统键击 WM_SYSKEYDOWN WM_SYSKEYUP

6.2.虚拟键代码

虚拟键代码存储在wParam参数中,此代码确定哪个键被按下或被释放。大多数虚拟机键代码命名都是以VK_开头的.

6.3.Iparam信息

wParam消息参数包含了虚拟键代码,Iparam消息参数包含了帮助理解击键的其它有用信息。32位的Iparam消息被分成了6个字段。

图片描述

  • 重复计数:是消息所表示的击键的数目
  • OEM扫描码:是键盘硬件产生的diamante,windows程序几乎可以忽略OEM扫描码
  • 扩展键标记:如果击键结果来自于IBM加强型键盘的附加减则扩展建标记为1,此项通常被忽略

  • 内容代码:如果在击键的同时页按下了Alt键,则内容代码为1

  • 键的先前状态:如果键以前是处于释放的,则键的先前状态为0。如果键以前是按下的,则键的先前状态为1

  • 转换状态:如果键正在被按下,转换状态为0,如果键正在被释放,转换状态为1.

6.4.转义状态

当处理击键消息时,可能需要知道是否有转义键(shift,ctrl,alt键)或切换键(caps lock、num lock、和scroll lock键)被按下,可以通过GetKeyState函数获得此信息。

1

2

3

4

5

//如果shift键被按下,则iState变量为负(即最高位为1

iState = GetKeyState(VK_SHIFT);

//如果Caps Lock键打开,则返回的值最低位置为1

iState = GetKeyState(VK_CAPITAL);

6.5.为SYSMETS加上键盘处理

给第4章SYSMETS程序添加键盘消息处理,使用SengMessage函数,可以通过给窗口过程发送假冒的消息欺骗WndProc函数,使它认为收到了滚动条消息。

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

case WM_KEYDOWN:

     switch (wParam)

     {

     case VK_HOME:

          SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0) ;

          break ;

     case VK_END:

          SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0) ;

          break ;

     case VK_PRIOR:

          SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0) ;

          break ;

     case VK_NEXT:

          SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0) ;

          break ;

     case VK_UP:

          SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0) ;

          break ;

     case VK_DOWN:

          SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN, 0) ;

          break ;

     case VK_LEFT:

          SendMessage (hwnd, WM_HSCROLL, SB_PAGEUP, 0) ;

          break ;

     case VK_RIGHT:

          SendMessage (hwnd, WM_HSCROLL, SB_PAGEDOWN, 0) ;

          break ;

     }

     return 0 ;

6.6.字符消息

1

2

3

4

5

while (GetMessage(&msg, NULL, 0, 0))

{

    TranslateMessage(&msg);

    DispatchMessage(&msg);

}

这是WinMain函数中的消息循环。GetMessage函数从消息队列总取出下一条消息,天填入msg结构的字段。

DispatchMessage函数调用此消息的窗口过程。

TranslateMessage负责把击键消息转换为字符消息,如果击键消息时WM_KEYDOWN或WM_SYSKEYDOWN,且击键和转移状态组合产生了一个字符,则TranslateMessage函数把字符消息放入应用程序的消息队列。这个字符消息将被放在击键消息之后,GetMessage函数可从消息队列中获取此字符消息。

四类字符消息

windows程序会忽略其它三占用字符消息,仅处理WM_CHAR消息

字符 死字符
非系统字符 WM_CHAR WM_DEADCHAR
系统字符 WM_SYSCHAR WM_SYSDEADCHAR

6.7.消息排序

例如Caps Lock键没有锁定,则按下再释放A键时,相应的窗口过程会接收一下三个消息

消息 击键或代码
WM_KEYDOWN A的虚拟键代码(0x41)
WM_CHAR A的字符编码(0x61)
WM_KEYUP A的虚拟键代码(0x41)

如果输入大写字母A:按下shift键,再按下A键,释放A键,再释放shift键,则窗口过程接收五个消息

消息 击键或代码
WM_KEYDOWN 虚拟键代码VK_SHIFT(0X10)
WM_KEYDOWN A的虚拟键代码(0x41)
WM_CHAR A的字符编码(0x41)
WM_KEYUP A的虚拟键代码(0x41)
WM_KEYUP 虚拟键代码VK_SHIFT(0X10)

6.8.控制字符的处理

ctrl和字母键的组合会产生ASCII控制字符

击键 字符码 产生方法 ANSI C 转义码
空格键 0x08 Ctrl-H \b
Tab键 0x09 Ctrl-I \t
ctrl+回车 0x0A Ctrl-J \n
回车键 0X0D Ctrl-M \r
Esc键 0X1B Ctrl-[

我们按照一下的基本规则来处理击键和字符消息

  • 如果需要读取输入到窗口中的键盘字符,就处理WM_CHAR消息
  • 如果需要读取光标键、功能键、Delete键、Insert键、shift、ctrl和alt键则处理WM_KEYDOWN

Tab键、回车键、空格键和esc键看作控制字符,而不是虚拟按键,通常这样处理WM_CHAR消息

1

2

3

4

5

6

7

8

9

10

11

case WM_CHAR:

    switch(wParam)

    {

        case '\b':     //backspace

        case '\t':        //tab

        case '\n':        //linefeed

        case '\r':        //carriage return          

    }

6.9.插入符号

  • 插入符号:当你向程序中输入文本时,通常会有下划线、竖线或方框指示你输入的下一个字符将出现在屏幕上的位置
  • 光标:特指表示鼠标位置的位图图像,即鼠标指针

关于插入符号的函数

  • CreateCaret:创建和窗口关联的插入符号
  • SetCaretPos:设置窗口内的插入符号的位置
  • ShowCaret:显示插入符号
  • HideCaret:隐藏插入符号
  • DestoryCaret:销毁插入符号

仅当窗口具有输入焦点时,窗口中插入符号才有意义。程序中通过处理WM_SETFOCUS消息和WM_KILLFOCUS消息来决定

它是否具有输入焦点。

使用插入符号的主要规则:在窗口过程处理WM_SETFOCUS消息时调用CreateCaret函数,处理WM_KILLFOCUS消息时调用DestoryCaret函数。

七、鼠标

7.1.客户区鼠标消息

当鼠标移经窗口客户区时,窗口过程接收WM_MOUSEMOVE消息。

按钮 按下 释放 第二次按下按钮
左键 WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK
中键 WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK
右键 WM_RBUTTONDOWN WM_RBUTTONUP WM_RBUTTONDBLCLK

对所有消息来说,参数IParam包含了鼠标的位置消息

  • x = LOWORD(IParam);
  • y = HIWORD(IParam);

参数wParam表示鼠标按钮、shift和ctrl键的状态

  • MK_LBUTTON 按下左键
  • MK_MBUTTON 按下中键
  • MK_RBUTTON 按下右键
  • MK_SHIFT 按下shift键
  • MK_CONTROL 按下ctrl键

7.2.简单的鼠标处理示例

connect.c

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("Connect");

    HWND         hwnd;

    MSG          msg;

    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = NULL;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("Program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName, TEXT("Connect-the-Points Mouse Demo"),

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static POINT pt[MAXPOINTS];

    static int   iCount;

    HDC          hdc;

    int          i, j;

    PAINTSTRUCT  ps;

    switch (message)

    {

    case WM_LBUTTONDOWN:

        iCount = 0;

        InvalidateRect(hwnd, NULL, TRUE);   //清空客户区

        return 0;

    case WM_MOUSEMOVE:

        if (wParam & MK_LBUTTON && iCount < 1000)   //判断是否按下了左键

        {

            pt[iCount].x = GET_X_LPARAM(lParam);

            pt[iCount++].y = GET_Y_LPARAM(lParam);

            hdc = GetDC(hwnd);

            //画一个黑点,并保存点的坐标

            SetPixel(hdc, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0);

            ReleaseDC(hwnd, hdc);

        }

        return 0;

    case WM_LBUTTONUP:

        InvalidateRect(hwnd, NULL, FALSE);

        return 0;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        SetCursor(LoadCursor(NULL, IDC_WAIT));

        ShowCursor(TRUE);

        for (i = 0; i < iCount - 1; i++)

            for (j = i + 1; j < iCount; j++)

            {

                MoveToEx(hdc, pt[i].x, pt[i].y, NULL);

                LineTo(hdc, pt[j].x, pt[j].y);

            }

        ShowCursor(FALSE);

        SetCursor(LoadCursor(NULL, IDC_ARROW));

        EndPaint(hwnd, &ps);

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

7.3.鼠标双击

如果想让窗口过程接收鼠标双击消息,那么在调用RegisterClass初始化窗口类结构时,必须在窗口风格字段中包含标识符CS_DBLCLKS

  • wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

若窗口类的风格包含CS_DBLCLKS,那么双击后,窗口过程会接收如下消息:

  • WM_LBUTTONDOWN
  • WM_LBUTTONUP
  • WM_LBUTTONDBLCLK
  • WM_LBUTTONUP

7.3.非客户区鼠标消息

如果鼠标位于窗口内部除客户区外的其它区域,windows就会向窗口过程发送一个非客户取区消息。窗口的非客户区消息包括标题栏、菜单和滚动条。

系统一般不需要用户处理非客户区消息,用户只需要将这些消息发送给DefWindowProc.

如果鼠标在窗口的非客户区内移动,窗口过程就会接收WM_NCMOUSEMOVE(NC:nonclient)消息

按钮 按下 释放 第二次按下按钮
左键 WM_NCLBUTTONDOWN WM_NCLBUTTONUP WM_NCLBUTTONDBLCLK
中键 WM_NCMBUTTONDOWN WM_NCMBUTTONUP WM_NCMBUTTONDBLCLK
右键 WM_NCRBUTTONDOWN WM_NCRBUTTONUP WM_NCRBUTTONDBLCLK

非客户区鼠标消息参数

  • wParam:表示非客户区鼠标移动或单机的位置,它的值被设定成一个以HT(击中测试)为首的标识符。
  • IParam:低位包含x坐标,高位包含y坐标,这些坐标都是屏幕坐标,而不是客户区坐标

7.4.击中测试消息

WM_NCHITTEST表示“非客户区击中测试(nonclient hit test)”,这个消息的优先级高于其它所有的客户区和非客户区鼠标消息。参数IParam包含鼠标位置的屏幕坐标x和y。参数wParam没有用到。windows应用程序会把这个消息发送给DefWindowProc,然后WM_NCHITTEST消息来产生所有其它和鼠标位置相关的鼠标消息。

对非客户区消息来说,DefWindowProc处理WM_NCHITTEST消息后返回一个可用于鼠标消息参数wParam的值,

这个返回值可以是任何一个非客户区鼠标消息的wParam参数的值,也可以是如下所示的值

  • HTCLIENT 客户区
  • HTNOWHERE 不在任何窗口
  • HTTRANSPARENT 被另外一个窗口覆盖的窗口
  • HTERROR 是函数DefWindowProc产生一个警示声

如果DefWindowProc在处理WM_NCHITTEST消息之后返回HTCLIENT,则windows会将屏幕坐标转换成客户区坐标,并产生一个客户区鼠标消息。

如果DefWindowProc在处理WM_NCHITTEST消息之后返回HTNOWHERE,那么程序就能有效地阻止系统向窗口发送所有客户区和非客户区鼠标消息。此时,无论鼠标位于任何位置,鼠标按钮操作都将失效。

1

2

case WM_NCHITTEST:

    return (LRESULT)HTNOWHERE;

八、计时器

8.1.使用计时器的方法一

如果程序在整个运行过程中需要一个计时器,在WinMain函数中或处理WM-create消息时,调用SetTimer函数,在离开WinMain函数时或是处理WM_DESTROY消息时,调用KillTimer函数。

方法1

1

SetTimer(hwnd, 1, uiMsecInterval, NULL);

  • 参数1:窗口句柄
  • 参数2:是一个计时器ID
  • 参数3:是一个32位的无符号整数,它是以毫秒为单位的时间间隔

停止WM_TIMER消息

1

KillTimer(hwnd, 1);   //第二个参数是相应SetTimer使用的计时器ID

当窗口过程收到WM_TIMER消息时,wParam等于计时器的ID,IParam是0

Beeper1.c

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("Beeper1");

    HWND         hwnd;

    MSG          msg;

    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = NULL;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("Program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName, TEXT("Beeper1 Timer Demo"),

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static BOOL fFlipFlop = FALSE;

    HBRUSH      hBrush;

    HDC         hdc;

    PAINTSTRUCT ps;

    RECT        rc;

    switch (message)

    {

    case WM_CREATE:

        SetTimer(hwnd, ID_TIMER, 1000, NULL);   //设置计时器

        return 0;

    case WM_TIMER:

        MessageBeep(-1);

        fFlipFlop = !fFlipFlop;

        InvalidateRect(hwnd, NULL, FALSE);

        return 0;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        GetClientRect(hwnd, &rc);

        hBrush = CreateSolidBrush(fFlipFlop ? RGB(255, 0, 0) : RGB(0, 0, 255));

        FillRect(hdc, &rc, hBrush);

        EndPaint(hwnd, &ps);

        DeleteObject(hBrush);

        return 0;

    case WM_DESTROY:

        KillTimer(hwnd, ID_TIMER);    //删除计时器

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

8.2.使用计时器的方法二

第一种设计计时器的方法把WM_TIMER消息发送给正常的窗口过程。第二种方法则让你指挥windows把计时器消息发送到程序中的另一个函数。收到计时器消息的函数被称为回调函数。

定义一个回调函数TimerProc,这个函数值处理WM_TIMER消息

1

2

3

4

VOID CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)

{

    //处理WM_TIMER消息

}

说明

  • 参数1:调用SetTimer时指定的窗口句柄
  • 参数2:windows只发送WM_TIMER消息到TimerProc,所以消息参数总是WM_TIMER
  • 参数3:计时器的ID
  • 参数4:dwTime是从GetTickCount函数返回的值,它记录了自动windows启动到现在所逝去的毫秒数

使用回调函数处理WM_TIIMER消息时,SetTimer函数的第四个参数必须设置位回调函数的地址

1

SetTimer(hwnd, iTimerID, iMsecInterval, TimerProc);

Beeper2.c

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

VOID    CALLBACK TimerProc(HWND, UINT, UINT, DWORD);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("Beeper2");

    HWND         hwnd;

    MSG          msg;

    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = NULL;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("Program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName, TEXT("Beeper2 Timer Demo"),

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_CREATE:

        SetTimer(hwnd, ID_TIMER, 1000, TimerProc);   //设置计时器和回调函数

        return 0;

    case WM_DESTROY:

        KillTimer(hwnd, ID_TIMER);        //删除计时器

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

VOID CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)

{

    static BOOL fFlipFlop = FALSE;

    HBRUSH      hBrush;

    HDC         hdc;

    RECT        rc;

    MessageBeep(-1);

    fFlipFlop = !fFlipFlop;

    GetClientRect(hwnd, &rc);

    hdc = GetDC(hwnd);

    hBrush = CreateSolidBrush(fFlipFlop ? RGB(255, 0, 0) : RGB(0, 0, 255));

    FillRect(hdc, &rc, hBrush);

    ReleaseDC(hwnd, hdc);

    DeleteObject(hBrush);

}

九、子窗口控件

9.1.按钮类

BTNLOOK.c

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

148

149

//定义10中不同类型的按钮样式

struct

{

    int     iStyle;

    TCHAR* szText;

}

button[] =

{

     BS_PUSHBUTTON,      TEXT("PUSHBUTTON"),

     BS_DEFPUSHBUTTON,   TEXT("DEFPUSHBUTTON"),

     BS_CHECKBOX,        TEXT("CHECKBOX"),

     BS_AUTOCHECKBOX,    TEXT("AUTOCHECKBOX"),

     BS_RADIOBUTTON,     TEXT("RADIOBUTTON"),

     BS_3STATE,          TEXT("3STATE"),

     BS_AUTO3STATE,      TEXT("AUTO3STATE"),

     BS_GROUPBOX,        TEXT("GROUPBOX"),

     BS_AUTORADIOBUTTON, TEXT("AUTORADIO"),

     BS_OWNERDRAW,       TEXT("OWNERDRAW")

};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("BtnLook");

    HWND         hwnd;

    MSG          msg;

    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = NULL;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName, TEXT("Button Look"),

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static HWND  hwndButton[NUM];

    static RECT  rect;

    static TCHAR szTop[] = TEXT("message            wParam       lParam"),

        szUnd[] = TEXT("_______            ______       ______"),

        szFormat[] = TEXT("%-16s%04X-%04X    %04X-%04X"),

        szBuffer[50];

    static int   cxChar, cyChar;

    HDC          hdc;

    PAINTSTRUCT  ps;

    int          i;

    switch (message)

    {

    case WM_CREATE:

        cxChar = LOWORD(GetDialogBaseUnits());    //获取字符的默认字体的宽度

        cyChar = HIWORD(GetDialogBaseUnits());    //获取字符的默认字体的高度

        for (i = 0; i < NUM; i++)

            hwndButton[i] = CreateWindow(

                TEXT("button"),                                 //类名

                button[i].szText,                              //窗口文本       

                WS_CHILD | WS_VISIBLE | button[i].iStyle,      //窗口样式

                cxChar,                                        //x坐标            

                cyChar * (1 + 2 * i),                          //y坐标

                20 * cxChar,                                   //宽度

                7 * cyChar / 4,                                //高度

                hwnd,                                          //父窗口

                (HMENU)i,                                      //子窗口ID

                ((LPCREATESTRUCT)lParam)->hInstance,           //实例句柄

                NULL);                                         //额外参数

        return 0;

    case WM_SIZE:

        rect.left = 24 * cxChar;

        rect.top = 2 * cyChar;

        rect.right = LOWORD(lParam);

        rect.bottom = HIWORD(lParam);

        return 0;

    case WM_PAINT:

        InvalidateRect(hwnd, &rect, TRUE);

        hdc = BeginPaint(hwnd, &ps);

        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

        SetBkMode(hdc, TRANSPARENT);

        TextOut(hdc, 24 * cxChar, cyChar, szTop, lstrlen(szTop));

        TextOut(hdc, 24 * cxChar, cyChar, szUnd, lstrlen(szUnd));

        EndPaint(hwnd, &ps);

        return 0;

    case WM_DRAWITEM:

    case WM_COMMAND:

        ScrollWindow(hwnd, 0, -cyChar, &rect, &rect);

        hdc = GetDC(hwnd);

        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

        TextOut(hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1),

            szBuffer,

            wsprintf(szBuffer, szFormat,

                message == WM_DRAWITEM ? TEXT("WM_DRAWITEM") :

                TEXT("WM_COMMAND"),

                HIWORD(wParam), LOWORD(wParam),

                HIWORD(lParam), LOWORD(lParam)));

        ReleaseDC(hwnd, hdc);

        ValidateRect(hwnd, &rect);

        break;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

9.2.子窗口传递信息给父窗口

运行BTNLOOK时,在用鼠标单击一个按钮时,子窗口控件发送WM_COMMAND消息给其父窗口。

BTNLOOK俘获WM_COMMAND消息并显示wParam与IParam的值

  • LOWORD(wParam) :子窗口ID
  • HIWORD(wParam):通知码
  • IParam:子窗口句柄

通知码

按钮通知码标识符
BN_CLICKED 0
BN_PAINT 1
BN_HILITE或BN_PUSHED 2
BN_UNHILITE或BN_UNPUSHED 3
BN_DISABLE 4
BN_DOUBLECLICKED或BN_DBLCLK 5
BN_SETFOCUS 6
BN_KILLFOCUS 7

9.3.编辑类

PopPad1.c

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

/*-------------------------------------------------------

   POPPAD1.C -- Popup Editor using child window edit box

                (c) Charles Petzold, 1998

  -------------------------------------------------------*/

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

TCHAR szAppName[] = TEXT("PopPad1");

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    HWND     hwnd;

    MSG      msg;

    WNDCLASS wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = NULL;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName, szAppName,

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static HWND hwndEdit;

    switch (message)

    {

    case WM_CREATE:

        hwndEdit = CreateWindow(TEXT("edit"), NULL,

            WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |

            WS_BORDER | ES_LEFT | ES_MULTILINE |     //多行左对齐

            ES_AUTOHSCROLL | ES_AUTOVSCROLL,         //自动换行

            0, 0, 0, 0, hwnd, (HMENU)ID_EDIT,

            ((LPCREATESTRUCT)lParam)->hInstance, NULL);

        return 0;

    case WM_SETFOCUS:

        SetFocus(hwndEdit);

        return 0;

    case WM_SIZE:

        //编辑控件的大小设置位主窗口的尺寸

        MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);

        return 0;

    case WM_COMMAND:

        if (LOWORD(wParam) == ID_EDIT)

            if (HIWORD(wParam) == EN_ERRSPACE || HIWORD(wParam) == EN_MAXTEXT)

                MessageBox(hwnd, TEXT("Edit control out of space."),szAppName, MB_OK | MB_ICONSTOP);

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

9.4.编辑控件的通知消息

编辑控件向其父窗口发送WM_COMMAND消息,相应的wParam和IParam变量的含义

  • LOWORD(wParam):子窗口ID
  • HIWORD(wParam):通知码
  • IPARAM:子窗口句柄

通知码

  • EN_SETFOCUS:编辑控件得到了输入焦点
  • EN_KILLFOCUS:编辑控件失去了输入焦点
  • EN_CHANGE:编辑控件的内容将变化
  • EN_UPDATE:编辑控件的内容已变化
  • EN_ERRSPACE:编辑控件没有空间了
  • EN_MAXTEXT:编辑控件没有空间完成插入了
  • EN_HSCROLL:编辑控件水平滚动条被单击了
  • EN_VSCROLL:编辑控件垂直滚动条被单击了

9.5.列表框类

LBS_STANDARD列表框样式,包含最常用的样式

获取垂直滚动条的宽度

1

GetSystemMetrics(SM_CXVSCROLL);

创建列表框后,下一步就是向其中添加文本字符串。可以使用SendMessage向列表框的窗口过程发送消息来实现

添加

1

SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)szString);

删除

1

SendMessage(hwndList, LB_DELETESTRING, iIndex, (LPARAM)szString);

清除所有

1

SendMessage(hwndList, LB_RESETCONTENT, 0, (LPARAM)szString);

查看列表框中有多少个项目

1

iCount = SendMessage(hwndList, LB_GETCOUNT,0,0);

在收到来自WM_COMMAND消息时,可以使用LB_GETCUUSEL得到当前选中的索引值

1

iIndex = SendMessage(hwndList, LB_GETCOrsel,0,0);

接收来自列表框的消息

  • LOWORD(wParam):子窗口ID
  • HIWORD(wParam):通知码
  • IPARAM:子窗口句柄

通知码

  • LBN_ERRSPACE: -2
  • LBN_SELCHANGE: 1
  • LBN_DBLCLK: 2
  • LBN_SELCANCEL: 3
  • LBN_SETFOCUS: 4
  • LBN_KILLFOCUS: 5

9.6.列出文件

LB_DIR是列表框中功能最强的消息,下面的函数调用可将文件目录列表写入列表框中,这个文件目录可以包括子目录和有效的磁盘驱动器。

1

SendMessage(hwndList, LB_DIR,iAttr, (LPARAM)szFileSpec);

iAttr参数是文件属性代码

iAttr 数值 属性
DDL_READWRITE 0x0000 普通文件
DDL_READONLY 0x00001 只读文件
DDL_HIDDEN 0x0002 隐藏文件
DDL_SYSTEM 0x0004 系统文件
DDL_DIRECTORY 0x0010 子目录
DDL_ARCHIVE 0x0020 设置了存档位的文件

紧接着最高字节提供了一些额外的搜索条件

iAttr 数值 选项
DDL_DRIVERS 0X4000 包括驱动器字符
DDL_EXCLUSIVE 0X8000 只搜索指定的值

head.c

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

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

                     DDL_DIRECTORY | DDL_ARCHIVE  | DDL_DRIVES)

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

LRESULT CALLBACK ListProc(HWND, UINT, WPARAM, LPARAM);

WNDPROC OldList;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("head");

    HWND         hwnd;

    MSG          msg;

    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);

    wndclass.lpszMenuName = NULL;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName, TEXT("head"),

        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static BOOL     bValidFile;

    static BYTE     buffer[MAXREAD];

    static HWND     hwndList, hwndText;

    static RECT     rect;

    static TCHAR    szFile[MAX_PATH + 1];

    HANDLE          hFile;

    HDC             hdc;

    int             i, cxChar, cyChar;

    PAINTSTRUCT     ps;

    TCHAR           szBuffer[MAX_PATH + 1];

    switch (message)

    {

    case WM_CREATE:

        cxChar = LOWORD(GetDialogBaseUnits());

        cyChar = HIWORD(GetDialogBaseUnits());

        rect.left = 20 * cxChar;

        rect.top = 3 * cyChar;

        hwndList = CreateWindow(TEXT("listbox"), NULL,

            WS_CHILDWINDOW | WS_VISIBLE | LBS_STANDARD,

            cxChar, cyChar * 3,

            cxChar * 13 + GetSystemMetrics(SM_CXVSCROLL),

            cyChar * 10,

            hwnd, (HMENU)ID_LIST,

            (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),

            NULL);

        GetCurrentDirectory(MAX_PATH + 1, szBuffer);

        hwndText = CreateWindow(TEXT("static"), szBuffer,

            WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT,

            cxChar, cyChar, cxChar * MAX_PATH, cyChar,

            hwnd, (HMENU)ID_TEXT,

            (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),

            NULL);

        OldList = (WNDPROC)SetWindowLong(hwndList, GWL_WNDPROC,

            (LPARAM)ListProc);

        SendMessage(hwndList, LB_DIR, DIRATTR, (LPARAM)TEXT("*.*"));

        return 0;

    case WM_SIZE:

        rect.right = LOWORD(lParam);

        rect.bottom = HIWORD(lParam);

        return 0;

    case WM_SETFOCUS:

        SetFocus(hwndList);

        return 0;

    case WM_COMMAND:

        if (LOWORD(wParam) == ID_LIST && HIWORD(wParam) == LBN_DBLCLK)

        {

            if (LB_ERR == (i = SendMessage(hwndList, LB_GETCURSEL, 0, 0)))

                break;

            SendMessage(hwndList, LB_GETTEXT, i, (LPARAM)szBuffer);

            if (INVALID_HANDLE_VALUE != (hFile = CreateFile(szBuffer,

                GENERIC_READ, FILE_SHARE_READ, NULL,

                OPEN_EXISTING, 0, NULL)))

            {

                CloseHandle(hFile);

                bValidFile = TRUE;

                lstrcpy(szFile, szBuffer);

                GetCurrentDirectory(MAX_PATH + 1, szBuffer);

                if (szBuffer[lstrlen(szBuffer) - 1] != '\\')

                    lstrcat(szBuffer, TEXT("\\"));

                SetWindowText(hwndText, lstrcat(szBuffer, szFile));

            }

            else

            {

                bValidFile = FALSE;

                szBuffer[lstrlen(szBuffer) - 1] = '\0';

                // If setting the directory doesn't work, maybe it's

                // a drive change, so try that.

                if (!SetCurrentDirectory(szBuffer + 1))

                {

                    szBuffer[3] = ':';

                    szBuffer[4] = '\0';

                    SetCurrentDirectory(szBuffer + 2);

                }

                // Get the new directory name and fill the list box.

                GetCurrentDirectory(MAX_PATH + 1, szBuffer);

                SetWindowText(hwndText, szBuffer);

                SendMessage(hwndList, LB_RESETCONTENT, 0, 0);

                SendMessage(hwndList, LB_DIR, DIRATTR,

                    (LPARAM)TEXT("*.*"));

            }

            InvalidateRect(hwnd, NULL, TRUE);

        }

        return 0;

    case WM_PAINT:

        if (!bValidFile)

            break;

        if (INVALID_HANDLE_VALUE == (hFile = CreateFile(szFile, GENERIC_READ,

            FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)))

        {

            bValidFile = FALSE;

            break;

        }

        ReadFile(hFile, buffer, MAXREAD, &i, NULL);

        CloseHandle(hFile);

        // i now equals the number of bytes in buffer.

        // Commence getting a device context for displaying text.

        hdc = BeginPaint(hwnd, &ps);

        SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

        SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));

        SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));

        // Assume the file is ASCII

        DrawTextA(hdc, buffer, i, &rect, DTFLAGS);

        EndPaint(hwnd, &ps);

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

LRESULT CALLBACK ListProc(HWND hwnd, UINT message,

    WPARAM wParam, LPARAM lParam)

{

    if (message == WM_KEYDOWN && wParam == VK_RETURN)

        SendMessage(GetParent(hwnd), WM_COMMAND,

            MAKELONG(1, LBN_DBLCLK), (LPARAM)hwnd);

    return CallWindowProc(OldList, hwnd, message, wParam, lParam);

}

十、菜单和其他资源

10.1.向程序添加图标

IconDemo.c

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    TCHAR    szAppName[] = TEXT("IconDemo");

    HWND     hwnd;

    MSG      msg;

    WNDCLASS wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = NULL;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName, TEXT("Icon Demo"),

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static HICON hIcon;

    static int   cxIcon, cyIcon, cxClient, cyClient;

    HDC          hdc;

    HINSTANCE    hInstance;

    PAINTSTRUCT  ps;

    int          x, y;

    switch (message)

    {

    case WM_CREATE:

        hInstance = ((LPCREATESTRUCT)lParam)->hInstance;

        //获取图标的句柄

        hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));

        //获取图标的大小

        cxIcon = GetSystemMetrics(SM_CXICON);

        cyIcon = GetSystemMetrics(SM_CYICON);

        return 0;

    case WM_SIZE:

        cxClient = LOWORD(lParam);

        cyClient = HIWORD(lParam);

        return 0;

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        for (y = 0; y < cyClient; y += cyIcon)

            for (x = 0; x < cxClient; x += cxIcon)

                DrawIcon(hdc, x, y, hIcon);   //显示图标

        EndPaint(hwnd, &ps);

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

10.2.菜单

和菜单有关的概念

  • 紧挨着标题栏下面的菜单栏叫做主菜单或顶级菜单
  • 顶级菜单的下拉菜单叫弹出菜单(popup menu)或子菜单
  • 弹出菜单的菜单项可以被选中(checked)

菜单结构,每个菜单项由三个特征定义

  • 第一个特征:菜单显示什么
  • 第二个特征:是一个ID号或一个指向弹出菜单的句柄
  • 第三个特征:描述了菜单的属性,包括该菜单项是否被禁用、变灰或选中

定义菜单

  • 在为菜单中的一项输入文本时,可以输入一个符号&来指示windows在显示菜单时给紧接着&的下一个字符显示下划线
  • 如果选择inactive选项,则表示该菜单项是非活动的
  • Separator选项会在弹出菜单上绘制一条水平的分割线

在程序中引用菜单

大多数windows应用程序只有一个菜单,可以给菜单指定一个与程序名一样的文本名字

1

wndclass.IPszMenuName = szAppName;

也可以用LoadMenu函数把菜单资源加载到内存

1

2

3

4

5

6

7

8

9

10

11

wndclass.lpszMenuName = "IDR_MENU1";  

HMENU hMenu;

hMenu = LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU1));

//创建窗口的时候指定菜单句柄

hwnd = CreateWindow(szAppName, TEXT("Menu Demonstration"),

                WS_OVERLAPPEDWINDOW,

                CW_USEDEFAULT, CW_USEDEFAULT,

                CW_USEDEFAULT, CW_USEDEFAULT,

                NULL, hMenu, hInstance, NULL);

菜单和消息

当用户在菜单项之间移动光标或鼠标时,程序可以收到许多WM_MENUSELECT消息,WM_MENUSELECT的参数如下

  • LOWORD(wParam):所选的菜单项:菜单ID或弹出菜单的索引
  • HIWORD(wParam):选择标记
  • IParam:包含所选项的菜单句柄

windows要显示弹出菜单时,会向窗口过程发送一个带有如下参数的WM_INITMENUPOPUP消息

  • wParam:弹出菜单的句柄

  • LOWORD(wParam):弹出菜单的索引

  • HIWORD(wParam):1代表系统菜单,0代表其它菜单

最重要的菜单消息时WM_COMMAND,这个消息表示用户已经从窗口菜单中选择了一个被启用的菜单项

菜单 控件
LOWORD(wParam) 菜单ID 控件ID
HIWORD(wParam) 0 通知码
IParam 0 子窗口句柄

示例程序MenuDemo

IDR_MENU1.rc

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

// Microsoft Visual C++ generated resource script.

//

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

// 中文(简体,中国) resources

LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

/////////////////////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE

BEGIN

    "#include ""winres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE

BEGIN

    "\r\n"

    "\0"

END

/////////////////////////////////////////////////////////////////////////////

//

// Menu

//

IDR_MENU1 MENU

BEGIN

    POPUP "&File"

    BEGIN

        MENUITEM "&New",                        ID_FILE_NEW

        MENUITEM "&Open",                       ID_FILE_OPEN

        MENUITEM "&Save",                       ID_FILE_SAVE

        MENUITEM "Save &As...",                 ID_FILE_SAVEAS

        MENUITEM SEPARATOR

        MENUITEM "E&xit",                       ID_FILE_EXIT

    END

    POPUP "&Edit"

    BEGIN

        MENUITEM "&Undo",                       ID_EDIT_UNDO

        MENUITEM SEPARATOR

        MENUITEM "C&ut",                        ID_EDIT_CUT

        MENUITEM "&Copy",                       ID_EDIT_COPY

        MENUITEM "&Paste",                      ID_EDIT_PASTE

        MENUITEM "De&lete",                     ID_EDIT_DELETE

    END

    POPUP "&Background"

    BEGIN

        MENUITEM "&White",                      ID_BACKGROUND_WHITE, CHECKED

        MENUITEM "&Light Gray",                 ID_BACKGROUND_WHITEGRAY

        MENUITEM "&Gray",                       ID_BACKGROUND_GRAY

        MENUITEM "&Dark Gray",                  ID_BACKGROUND_DARKGRAY

        MENUITEM "&Black",                      ID_BACKGROUND_BLACK

    END

    POPUP "&Timer"

    BEGIN

        MENUITEM "&Start",                      ID_TIMER_START

        MENUITEM "S&top",                       ID_TIMER_STOP, INACTIVE

    END

    POPUP "&Help"

    BEGIN

        MENUITEM "&Help...",                    ID_HELP_HELP

        MENUITEM "&About MenuDemo...",          ID_HELP_ABOUTMENUDEMO

    END

END

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

/////////////////////////////////////////////////////////////////////////////

resource.h

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

//{{NO_DEPENDENCIES}}

// Microsoft Visual C++ 生成的包含文件。

// 供 IDR_MENU1.rc 使用

//

// Next default values for new objects

//

MenuDemo.c

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

TCHAR szAppName[] = TEXT("MenuDemo");

TCHAR szMenuName[] = TEXT("IDR_MENU1");

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    HWND     hwnd;

    MSG      msg;

    WNDCLASS wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = szMenuName;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    //把菜单资源加载到内存

    HMENU hMenu;

    hMenu = LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU1));

    hwnd = CreateWindow(szAppName, TEXT("Menu Demonstration"),

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, hMenu, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static int idColor[5] = { WHITE_BRUSH,  LTGRAY_BRUSH, GRAY_BRUSH,

                               DKGRAY_BRUSH, BLACK_BRUSH };

    static int iSelection = ID_BACKGROUND_WHITE;

    HMENU      hMenu;

    switch (message)

    {

    case WM_COMMAND:

        hMenu = GetMenu(hwnd);

        switch (LOWORD(wParam))    //控件ID

        {

        case ID_FILE_NEW:

        case ID_FILE_OPEN:

        case ID_FILE_SAVE:

        case ID_FILE_SAVEAS:

            MessageBeep(0);

            return 0;

        case ID_FILE_EXIT:

            SendMessage(hwnd, WM_CLOSE, 0, 0);

            return 0;

        case ID_EDIT_UNDO:

        case ID_EDIT_CUT:

        case ID_EDIT_COPY:

        case ID_EDIT_PASTE:

        case ID_EDIT_DELETE:

            MessageBeep(0);

            return 0;

        case ID_BACKGROUND_WHITE:         // Note: Logic below

        case ID_BACKGROUND_WHITEGRAY:        //   assumes that IDM_WHITE

        case ID_BACKGROUND_GRAY:          //   through IDM_BLACK are

        case ID_BACKGROUND_DARKGRAY:        //   consecutive numbers in

        case ID_BACKGROUND_BLACK:         //   the order shown here.

            //取消对当前选中项的选中标注

            CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);

            //iSelection设为菜单ID

            iSelection = LOWORD(wParam);

            CheckMenuItem(hMenu, iSelection, MF_CHECKED);

            //设置新的背景颜色

            SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)

                GetStockObject

                (idColor[LOWORD(wParam) - ID_BACKGROUND_WHITE]));

            InvalidateRect(hwnd, NULL, TRUE);

            return 0;

        case ID_TIMER_START:

            //启动计时器

            if (SetTimer(hwnd, ID_TIMER, 1000, NULL))

            {

                EnableMenuItem(hMenu, ID_TIMER_START, MF_GRAYED);   //start项变灰

                EnableMenuItem(hMenu, ID_TIMER_STOP, MF_ENABLED);   //stop项激活

            }

            return 0;

        case ID_TIMER_STOP:

            KillTimer(hwnd, ID_TIMER);   //终止计时器

            EnableMenuItem(hMenu, ID_TIMER_START, MF_ENABLED);  //start项激活

            EnableMenuItem(hMenu, ID_TIMER_STOP, MF_GRAYED);    //stop项变灰

            return 0;

        case ID_HELP_HELP:

            MessageBox(hwnd, TEXT("Help not yet implemented!"),

                szAppName, MB_ICONEXCLAMATION | MB_OK);

            return 0;

        case ID_HELP_ABOUTMENUDEMO:

            MessageBox(hwnd, TEXT("Menu Demonstration Program\n")

                TEXT("(c) Charles Petzold, 1998"),

                szAppName, MB_ICONINFORMATION | MB_OK);

            return 0;

        }

        break;

    case WM_TIMER:

        MessageBeep(0);

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

10.3.键盘加速键

指定加速键的一些规则

键盘加速键最常用的用途是用于程序中Edit菜单的菜单项,同时支持新旧两种加速键

功能 旧加速键 新加速键
Undo(撤销) Alt+Backspace Ctrl+Z
Cut(剪切) Shift+Del Ctrl+X
Copy(复制) Ctrl+Ins Ctrl+C
Paste(粘贴) Shift+Ins Ctrl+V
Delete或Clear(删除) Del Del

加速键表

  • 可以在字母前加^来指定ASCII字符与Ctrl键的组合,也可以从组合框中选择虚拟机按键码
  • 在为菜单项定义键盘加速键时,\t能将文本和加速键分开

接收加速键消息

加速键 菜单 控件
LOWORD(wParam) 加速键ID 菜单ID 控件ID
HIWORD(wParam) 1 0 通知码
IParam 0 0 子窗口句柄

实例:记事本程序PopPad2

键盘加速键IDR_ACCELERATOR1

图片描述

IDR_MENU1

图片描述

resource.h

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

//{{NO_DEPENDENCIES}}

// Microsoft Visual C++ 生成的包含文件。

// 供 PopPad2.rc 使用

//

//

// Next default values for new objects

//

PopPad2.rc

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

// Microsoft Visual C++ generated resource script.

//

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

// 中文(简体,中国) resources

LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

/////////////////////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE

BEGIN

    "#include ""winres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE

BEGIN

    "\r\n"

    "\0"

END

/////////////////////////////////////////////////////////////////////////////

//

// Menu

//

IDR_MENU1 MENU

BEGIN

    POPUP "&File"

    BEGIN

        MENUITEM "&New",                        ID_FILE_NEW

        MENUITEM "&Open",                       ID_FILE_OPEN

        MENUITEM "&Save",                       ID_FILE_SAVE

        MENUITEM "Save &As...",                 ID_FILE_SAVEAS

        MENUITEM SEPARATOR

        MENUITEM "&Print",                      ID_FILE_PRINT

        MENUITEM SEPARATOR

        MENUITEM "E&xit",                       ID_FILE_EXIT

    END

    POPUP "&Eidt"

    BEGIN

        MENUITEM "&Undo\tCtrl+Z",               ID_EIDT_UNDO

        MENUITEM SEPARATOR

        MENUITEM "Cu&t\tCtrl+X",                ID_EIDT_CUT

        MENUITEM "&Copy\tCtrl+C",               ID_EIDT_COPY

        MENUITEM "&Paste\tCtrl+V",              ID_EIDT_PASTE

        MENUITEM "De&lete\tCtrl+Del",           ID_EIDT_DELETE

        MENUITEM SEPARATOR

        MENUITEM "&Selete All",                 ID_EIDT_SELETEALL

    END

    POPUP "&Help"

    BEGIN

        MENUITEM "&Help",                       ID_HELP_HELP

        MENUITEM "&About PopPad2...",           ID_HELP_ABOUTPOPPAD2

    END

END

/////////////////////////////////////////////////////////////////////////////

//

// Accelerator

//

POPPAD2 ACCELERATORS

BEGIN

    VK_BACK,        ID_EIDT_UNDO,           VIRTKEY, ALT, NOINVERT

    VK_DELETE,      ID_EIDT_DELETE,         VIRTKEY, NOINVERT

    VK_DELETE,      ID_EIDT_CUT,            VIRTKEY, SHIFT, NOINVERT

    VK_F1,          ID_HELP_HELP,           VIRTKEY, NOINVERT

    VK_INSERT,      ID_EIDT_COPY,           VIRTKEY, CONTROL, NOINVERT

    VK_INSERT,      ID_EIDT_PASTE,          VIRTKEY, SHIFT, NOINVERT

    "^C",           ID_EIDT_COPY,           ASCII,  NOINVERT

    "^V",           ID_EIDT_PASTE,          ASCII,  NOINVERT

    "^X",           ID_EIDT_CUT,            ASCII,  NOINVERT

    "^Z",           ID_EIDT_UNDO,           ASCII,  NOINVERT

END

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

/////////////////////////////////////////////////////////////////////////////

PopPad2.c

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

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

TCHAR szAppName[] = TEXT("PopPad2");

TCHAR szMenuName[] = TEXT("IDR_MENU1");  

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    HACCEL   hAccel;

    HWND     hwnd;

    MSG      msg;

    WNDCLASS wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(hInstance, szAppName);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = szMenuName;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    HMENU hMenu;

    hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));

    hwnd = CreateWindow(szAppName, szAppName,

        WS_OVERLAPPEDWINDOW,

        GetSystemMetrics(SM_CXSCREEN) / 4,

        GetSystemMetrics(SM_CYSCREEN) / 4,

        GetSystemMetrics(SM_CXSCREEN) / 2,

        GetSystemMetrics(SM_CYSCREEN) / 2,

        NULL, hMenu, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    //把加速键表加载到内存并获得它的句柄

    hAccel = LoadAccelerators(hInstance, szAppName);   

    while (GetMessage(&msg, NULL, 0, 0))

    {

        //处理菜单命令的快捷键。 如果指定快捷键表中有项) ,然后将WM_COMMAND或WM_SYSCOMMAND消息直接发送到

        //指定的窗口过程,则该函数会将WM_KEYDOWN或WM_SYSKEYDOWN消息转换为WM_COMMAND或WM_SYSCOMMAND消息

        if (!TranslateAccelerator(hwnd, hAccel, &msg))

        {

            TranslateMessage(&msg);

            DispatchMessage(&msg);

        }

    }

    return msg.wParam;

}

AskConfirmation(HWND hwnd)

{

    return MessageBox(hwnd, TEXT("Really want to close PopPad2?"),

        szAppName, MB_YESNO | MB_ICONQUESTION);

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static HWND hwndEdit;

    int         iSelect, iEnable;

    switch (message)

    {

    case WM_CREATE:

        hwndEdit = CreateWindow(TEXT("edit"), NULL,

            WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |

            WS_BORDER | ES_LEFT | ES_MULTILINE |

            ES_AUTOHSCROLL | ES_AUTOVSCROLL,

            0, 0, 0, 0, hwnd, (HMENU)ID_EDIT,

            ((LPCREATESTRUCT)lParam)->hInstance, NULL);

        return 0;

    case WM_SETFOCUS:

        SetFocus(hwndEdit);

        return 0;

    case WM_SIZE:

        MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);

        return 0;

    case WM_INITMENUPOPUP:

        //Edit在菜单中位置索引为1

        if (lParam == 1)

        {

            EnableMenuItem((HMENU)wParam, ID_EIDT_UNDO,

                SendMessage(hwndEdit, EM_CANUNDO, 0, 0) ?

                MF_ENABLED : MF_GRAYED);

            //只有当剪切板当前包好文本时,Paste菜单项才应该被启用

            EnableMenuItem((HMENU)wParam, ID_EIDT_PASTE,

                IsClipboardFormatAvailable(CF_TEXT) ?

                MF_ENABLED : MF_GRAYED);

            //只有在编辑控件中有文本被选中时,Cut、Copy和Deete选项才应该被启用

            iSelect = SendMessage(hwndEdit, EM_GETSEL, 0, 0);

            if (HIWORD(iSelect) == LOWORD(iSelect))

                iEnable = MF_GRAYED;

            else

                iEnable = MF_ENABLED;

            EnableMenuItem((HMENU)wParam, ID_EIDT_CUT, iEnable);

            EnableMenuItem((HMENU)wParam, ID_EIDT_COPY, iEnable);

            EnableMenuItem((HMENU)wParam, ID_EIDT_DELETE, iEnable);

            return 0;

        }

        break;

    case WM_COMMAND:

        if (lParam)

        {

            if (LOWORD(lParam) == ID_EDIT &&

                (HIWORD(wParam) == EN_ERRSPACE ||

                    HIWORD(wParam) == EN_MAXTEXT))

                MessageBox(hwnd, TEXT("Edit control out of space."),

                    szAppName, MB_OK | MB_ICONSTOP);

            return 0;

        }

        else switch (LOWORD(wParam))

        {

        case ID_FILE_NEW:

        case ID_FILE_OPEN:

        case ID_FILE_SAVE:

        case ID_FILE_SAVEAS:

        case ID_FILE_PRINT:

            MessageBeep(0);

            return 0;

        case ID_FILE_EXIT:

            SendMessage(hwnd, WM_CLOSE, 0, 0);

            return 0;

        case ID_EIDT_UNDO:

            SendMessage(hwndEdit, WM_UNDO, 0, 0);

            return 0;

        case ID_EIDT_CUT:

            SendMessage(hwndEdit, WM_CUT, 0, 0);

            return 0;

        case ID_EIDT_COPY:

            SendMessage(hwndEdit, WM_COPY, 0, 0);

            return 0;

        case ID_EIDT_PASTE:

            SendMessage(hwndEdit, WM_PASTE, 0, 0);

            return 0;

        case ID_EIDT_DELETE:

            SendMessage(hwndEdit, WM_CLEAR, 0, 0);

            return 0;

        case ID_EIDT_SELETEALL:

            SendMessage(hwndEdit, EM_SETSEL, 0, -1);

            return 0;

        case ID_HELP_HELP:

            MessageBox(hwnd, TEXT("Help not yet implemented!"),

                szAppName, MB_OK | MB_ICONEXCLAMATION);

            return 0;

        case ID_HELP_ABOUTPOPPAD2:

            MessageBox(hwnd, TEXT("POPPAD2 (c) Charles Petzold, 1998"),

                szAppName, MB_OK | MB_ICONINFORMATION);

            return 0;

        }

        break;

    case WM_CLOSE:

        if (IDYES == AskConfirmation(hwnd))

            DestroyWindow(hwnd);

        return 0;

    case WM_QUERYENDSESSION:

        if (IDYES == AskConfirmation(hwnd))

            return 1;

        else

            return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

十一、对话框

11.1.模态对话框

创建一个About1对话框

About1.rc

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

// Microsoft Visual C++ generated resource script.

//

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

// 中文(简体,中国) resources

LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

/////////////////////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE

BEGIN

    "#include ""winres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE

BEGIN

    "\r\n"

    "\0"

END

/////////////////////////////////////////////////////////////////////////////

//

// Icon

//

// Icon with lowest ID value placed first to ensure application icon

// remains consistent on all systems.

ABOUT1                  ICON                    "About1.ico"

/////////////////////////////////////////////////////////////////////////////

//

// Dialog

//

AboutBox DIALOGEX 32, 32, 211, 127

STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_SYSMENU

FONT 8, "MS Shell Dlg", 400, 0, 0x1

BEGIN

    DEFPUSHBUTTON   "确定",IDOK,79,99,50,14

    LTEXT           "About1",IDC_STATIC,82,29,42,8

    LTEXT           "About Derek Demo",IDC_STATIC,70,50,101,15

    LTEXT           "derek 2022/12/12",IDC_STATIC,69,70,124,13

    ICON            "About1",IDC_STATIC,17,23,20,20

END

/////////////////////////////////////////////////////////////////////////////

//

// Menu

//

IDR_MENU1 MENU

BEGIN

    POPUP "Help"

    BEGIN

        MENUITEM "About About1...",             ID_HELP_ABOUTABOUT1

    END

END

/////////////////////////////////////////////////////////////////////////////

//

// DESIGNINFO

//

GUIDELINES DESIGNINFO

BEGIN

    "AboutBox", DIALOG

    BEGIN

        LEFTMARGIN, 7

        RIGHTMARGIN, 204

        TOPMARGIN, 7

        BOTTOMMARGIN, 120

    END

END

/////////////////////////////////////////////////////////////////////////////

//

// AFX_DIALOG_LAYOUT

//

AboutBox AFX_DIALOG_LAYOUT

BEGIN

    0

END

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

/////////////////////////////////////////////////////////////////////////////

resource.h

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

//{{NO_DEPENDENCIES}}

// Microsoft Visual C++ 生成的包含文件。

// 供 About1.rc 使用

//

// Next default values for new objects

//

About1.c

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

BOOL    CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("About1");

    static TCHAR szMenuName[] = TEXT("IDR_MENU1");

    MSG          msg;

    HWND         hwnd;

    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(hInstance, szAppName);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = szMenuName;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    HMENU hMenu;

    hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));

    hwnd = CreateWindow(szAppName, TEXT("About Box Demo Program"),

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, hMenu, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static HINSTANCE hInstance;

    switch (message)

    {

    case WM_CREATE:

        hInstance = ((LPCREATESTRUCT)lParam)->hInstance;

        return 0;

    case WM_COMMAND:

        switch (LOWORD(wParam))

        {

        case ID_HELP_ABOUTABOUT1:

            DialogBox(hInstance, TEXT("AboutBox"), hwnd, AboutDlgProc);

            break;

        }

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message,

    WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_INITDIALOG:

        return TRUE;

    case WM_COMMAND:

        switch (LOWORD(wParam))

        {

        case IDOK:

        case IDCANCEL:

            EndDialog(hDlg, 0);

            return TRUE;

        }

        break;

    }

    return FALSE;

}

11.2.更复杂的对话框

About2.rc

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

// Microsoft Visual C++ generated resource script.

//

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

// 中文(简体,中国) resources

LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

/////////////////////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE

BEGIN

    "#include ""winres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE

BEGIN

    "\r\n"

    "\0"

END

/////////////////////////////////////////////////////////////////////////////

//

// Icon

//

// Icon with lowest ID value placed first to ensure application icon

// remains consistent on all systems.

ABOUT2               ICON                    "ABOUT2.ico"

/////////////////////////////////////////////////////////////////////////////

//

// Menu

//

IDR_MENU1 MENU

BEGIN

    POPUP "Help"

    BEGIN

        MENUITEM "About",                       ID_HELP_ABOUT

    END

END

/////////////////////////////////////////////////////////////////////////////

//

// Dialog

//

AboutBox DIALOGEX 0, 0, 359, 219

STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_SYSMENU

FONT 8, "MS Shell Dlg", 400, 0, 0x1

BEGIN

    DEFPUSHBUTTON   "确定",IDOK,77,191,50,14

    PUSHBUTTON      "取消",IDCANCEL,155,188,50,14

    ICON            "About2",IDC_STATIC,18,19,21,20

    LTEXT           "About2",IDC_STATIC,102,15,81,17

    LTEXT           "About derek Demo Program",IDC_STATIC,67,32,184,10

    GROUPBOX        "Color",IDC_STATIC,36,52,81,127

    RADIOBUTTON     "Black",IDC_BLACK,44,63,32,10,WS_TABSTOP

    RADIOBUTTON     "Blue",IDC_BLUE,44,77,29,10

    RADIOBUTTON     "Green",IDC_GREEN,44,91,35,10

    RADIOBUTTON     "Cyan",IDC_CYAN,44,105,33,10

    RADIOBUTTON     "Red",IDC_RED,44,119,29,10

    RADIOBUTTON     "Magenta",IDC_MAGENTA,43,133,44,10

    RADIOBUTTON     "Yellow",IDC_YELLOW,43,147,36,10

    RADIOBUTTON     "White",IDC_WHITE,44,161,35,10

    GROUPBOX        "Figure",IDC_STATIC,209,126,83,49

    RADIOBUTTON     "Rectangle",IDC_RECT,215,140,48,10,WS_TABSTOP

    RADIOBUTTON     "Elipse",IDC_ELLIPSE,215,158,34,10

    LISTBOX         IDC_PAINT,191,52,116,63,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP

END

/////////////////////////////////////////////////////////////////////////////

//

// DESIGNINFO

//

GUIDELINES DESIGNINFO

BEGIN

    AboutBox, DIALOG

    BEGIN

        LEFTMARGIN, 7

        RIGHTMARGIN, 352

        TOPMARGIN, 7

        BOTTOMMARGIN, 212

    END

END

/////////////////////////////////////////////////////////////////////////////

//

// AFX_DIALOG_LAYOUT

//

AboutBox AFX_DIALOG_LAYOUT

BEGIN

    0

END

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

/////////////////////////////////////////////////////////////////////////////

resource.h

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

//{{NO_DEPENDENCIES}}

// Microsoft Visual C++ 生成的包含文件。

// 供 About2.rc 使用

//

// Next default values for new objects

//

About2.c

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

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

/*------------------------------------------

   ABOUT2.C -- About Box Demo Program No. 2

               (c) Charles Petzold, 1998

  ------------------------------------------*/

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

BOOL    CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);

int iCurrentColor = IDC_BLACK,

iCurrentFigure = IDC_RECT;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    static TCHAR szAppName[] = TEXT("About2");

    static TCHAR szMenuName[] = TEXT("IDR_MENU1");

    MSG          msg;

    HWND         hwnd;

    WNDCLASS     wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(hInstance, szAppName);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = szMenuName;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    HMENU hMenu;

    hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));

    hwnd = CreateWindow(szAppName, TEXT("About Box Demo Program"),

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, hMenu, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

void PaintWindow(HWND hwnd, int iColor, int iFigure)

{

    static COLORREF crColor[8] = { RGB(0,   0, 0), RGB(0,   0, 255),

                                   RGB(0, 255, 0), RGB(0, 255, 255),

                                   RGB(255,   0, 0), RGB(255,   0, 255),

                                   RGB(255, 255, 0), RGB(255, 255, 255) };

    HBRUSH          hBrush;

    HDC             hdc;

    RECT            rect;

    hdc = GetDC(hwnd);

    GetClientRect(hwnd, &rect);

    hBrush = CreateSolidBrush(crColor[iColor - IDC_BLACK]);

    hBrush = (HBRUSH)SelectObject(hdc, hBrush);

    if (iFigure == IDC_RECT)

        Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);

    else

        Ellipse(hdc, rect.left, rect.top, rect.right, rect.bottom);

    DeleteObject(SelectObject(hdc, hBrush));

    ReleaseDC(hwnd, hdc);

}

void PaintTheBlock(HWND hCtrl, int iColor, int iFigure)

{

    InvalidateRect(hCtrl, NULL, TRUE);

    UpdateWindow(hCtrl);

    PaintWindow(hCtrl, iColor, iFigure);

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static HINSTANCE hInstance;

    PAINTSTRUCT      ps;

    switch (message)

    {

    case WM_CREATE:

        hInstance = ((LPCREATESTRUCT)lParam)->hInstance;

        return 0;

    case WM_COMMAND:

        switch (LOWORD(wParam))

        {

        case ID_HELP_ABOUT:

            if (DialogBox(hInstance, TEXT("AboutBox"), hwnd, AboutDlgProc))

                InvalidateRect(hwnd, NULL, TRUE);

            return 0;

        }

        break;

    case WM_PAINT:

        BeginPaint(hwnd, &ps);

        EndPaint(hwnd, &ps);

        PaintWindow(hwnd, iCurrentColor, iCurrentFigure);

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message,

    WPARAM wParam, LPARAM lParam)

{

    static HWND hCtrlBlock;

    static int  iColor, iFigure;

    switch (message)

    {

    case WM_INITDIALOG:

        iColor = iCurrentColor;

        iFigure = iCurrentFigure;

        CheckRadioButton(hDlg, IDC_BLACK, IDC_WHITE, iColor);

        CheckRadioButton(hDlg, IDC_RECT, IDC_ELLIPSE, iFigure);

        hCtrlBlock = GetDlgItem(hDlg, IDC_PAINT);

        SetFocus(GetDlgItem(hDlg, iColor));

        return FALSE;

    case WM_COMMAND:

        switch (LOWORD(wParam))

        {

        case IDOK:

            iCurrentColor = iColor;

            iCurrentFigure = iFigure;

            EndDialog(hDlg, TRUE);

            return TRUE;

        case IDCANCEL:

            EndDialog(hDlg, FALSE);

            return TRUE;

        case IDC_BLACK:

        case IDC_RED:

        case IDC_GREEN:

        case IDC_YELLOW:

        case IDC_BLUE:

        case IDC_MAGENTA:

        case IDC_CYAN:

        case IDC_WHITE:

            iColor = LOWORD(wParam);

            CheckRadioButton(hDlg, IDC_BLACK, IDC_WHITE, LOWORD(wParam));

            PaintTheBlock(hCtrlBlock, iColor, iFigure);

            return TRUE;

        case IDC_RECT:

        case IDC_ELLIPSE:

            iFigure = LOWORD(wParam);

            CheckRadioButton(hDlg, IDC_RECT, IDC_ELLIPSE, LOWORD(wParam));

            PaintTheBlock(hCtrlBlock, iColor, iFigure);

            return TRUE;

        }

        break;

    case WM_PAINT:

        PaintTheBlock(hCtrlBlock, iColor, iFigure);

        break;

    }

    return FALSE;

}

11.3.项目PopPad3

resource.h

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

//{{NO_DEPENDENCIES}}

// Microsoft Visual C++ 生成的包含文件。

// 供 PopPad3.rc 使用

//

//

//

//

// Next default values for new objects

//

PopPad3.rc

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

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

// Microsoft Visual C++ generated resource script.

//

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 2 resource.

//

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

// 中文(简体,中国) resources

LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

/////////////////////////////////////////////////////////////////////////////

//

// TEXTINCLUDE

//

1 TEXTINCLUDE

BEGIN

    "resource.h\0"

END

2 TEXTINCLUDE

BEGIN

    "#include ""winres.h""\r\n"

    "\0"

END

3 TEXTINCLUDE

BEGIN

    "\r\n"

    "\0"

END

/////////////////////////////////////////////////////////////////////////////

//

// Icon

//

// Icon with lowest ID value placed first to ensure application icon

// remains consistent on all systems.

POPPAD                  ICON                    "poppad.ico"

/////////////////////////////////////////////////////////////////////////////

//

// Menu

//

POPPAD MENU

BEGIN

    POPUP "&File"

    BEGIN

        MENUITEM "&New\tCtrl+N",                ID_FILE_NEW

        MENUITEM "&Open...\tCtrl+O",            ID_FILE_OPEN

        MENUITEM "&Save\tCtrl+S",               ID_FILE_SAVE

        MENUITEM "Save &As...",                 ID_FILE_SAVEAS

        MENUITEM SEPARATOR

        MENUITEM "&Print\tCtrl+P",              ID_FILE_PRINT

        MENUITEM SEPARATOR

        MENUITEM "E&xit",                       ID_FILE_EXIT

    END

    POPUP "&Edit"

    BEGIN

        MENUITEM "&Undo\tCtrl+Z",               ID_EDIT_UNDO

        MENUITEM SEPARATOR

        MENUITEM "Cu&t\tCtrl+X",                ID_EDIT_CUT

        MENUITEM "&Copy\tCtrl+C",               ID_EDIT_COPY

        MENUITEM "&Paste\tCtrl+V",              ID_EDIT_PASTE

        MENUITEM "De&lete\tDel",                ID_EDIT_DELETE

        MENUITEM SEPARATOR

        MENUITEM "&Select All",                 ID_EDIT_SELECTALL

    END

    POPUP "&Search"

    BEGIN

        MENUITEM "&Find...\tCtrl+F",            ID_SEARCH_FIND

        MENUITEM "Find &Next\tF3",              ID_SEARCH_FINDNEXT

        MENUITEM "&Replace...\tCtrl+R",         ID_SEARCH_REPLACE

    END

    POPUP "F&ormat"

    BEGIN

        MENUITEM "&Font...",                    ID_FORMAT_FONT

    END

    POPUP "&Help"

    BEGIN

        MENUITEM "&Help",                       ID_HELP_HELP

        MENUITEM "&About PopPad...",            ID_HELP_ABOUTPOPPAD

    END

END

/////////////////////////////////////////////////////////////////////////////

//

// Dialog

//

ABOUTBOX DIALOGEX 32, 32, 190, 129

STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_SYSMENU

FONT 8, "MS Shell Dlg", 400, 0, 0x1

BEGIN

    DEFPUSHBUTTON   "确定",IDOK,65,92,50,14

    LTEXT           "PopPad",IDC_STATIC,72,18,57,15

    LTEXT           "Popup Editor for Windows",IDC_STATIC,48,42,104,14

    LTEXT           "by derek,20221214",IDC_STATIC,48,63,114,18

    ICON            "POPPAD",IDC_STATIC,17,17,20,20

END

/////////////////////////////////////////////////////////////////////////////

//

// Accelerator

//

POPPAD ACCELERATORS

BEGIN

    "^C",           ID_EDIT_COPY,           ASCII,  NOINVERT

    "^X",           ID_EDIT_CUT,            ASCII,  NOINVERT

    "^V",           ID_EDIT_PASTE,          ASCII,  NOINVERT

    "^Z",           ID_EDIT_UNDO,           ASCII,  NOINVERT

    "^N",           ID_FILE_NEW,            ASCII,  NOINVERT

    "^O",           ID_FILE_OPEN,           ASCII,  NOINVERT

    "^P",           ID_FILE_PRINT,          ASCII,  NOINVERT

    "^S",           ID_FILE_SAVE,           ASCII,  NOINVERT

    "^F",           ID_SEARCH_FIND,         ASCII,  NOINVERT

    "^R",           ID_SEARCH_REPLACE,      ASCII,  NOINVERT

END

/////////////////////////////////////////////////////////////////////////////

//

// DESIGNINFO

//

GUIDELINES DESIGNINFO

BEGIN

    "ABOUTBOX", DIALOG

    BEGIN

        LEFTMARGIN, 7

        RIGHTMARGIN, 183

        TOPMARGIN, 7

        BOTTOMMARGIN, 122

    END

END

/////////////////////////////////////////////////////////////////////////////

//

// AFX_DIALOG_LAYOUT

//

ABOUTBOX AFX_DIALOG_LAYOUT

BEGIN

    0

END

/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

//

// Generated from the TEXTINCLUDE 3 resource.

//

/////////////////////////////////////////////////////////////////////////////

PopPad3.c

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

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

/*---------------------------------------

   POPPAD.C -- Popup Editor

               (c) Charles Petzold, 1998

  ---------------------------------------*/

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

BOOL    CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);

// Functions in POPFILE.C

void PopFileInitialize(HWND);

BOOL PopFileOpenDlg(HWND, PTSTR, PTSTR);

BOOL PopFileSaveDlg(HWND, PTSTR, PTSTR);

BOOL PopFileRead(HWND, PTSTR);

BOOL PopFileWrite(HWND, PTSTR);

// Functions in POPFIND.C

HWND PopFindFindDlg(HWND);

HWND PopFindReplaceDlg(HWND);

BOOL PopFindFindText(HWND, int*, LPFINDREPLACE);

BOOL PopFindReplaceText(HWND, int*, LPFINDREPLACE);

BOOL PopFindNextText(HWND, int*);

BOOL PopFindValidFind(void);

// Functions in POPFONT.C

void PopFontInitialize(HWND);

BOOL PopFontChooseFont(HWND);

void PopFontSetFont(HWND);

void PopFontDeinitialize(void);

// Functions in POPPRNT.C

BOOL PopPrntPrintFile(HINSTANCE, HWND, HWND, PTSTR);

// Global variables

static HWND  hDlgModeless;

static TCHAR szAppName[] = TEXT("PopPad");

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    PSTR szCmdLine, int iCmdShow)

{

    MSG       msg;

    HWND      hwnd;

    HACCEL    hAccel;

    WNDCLASS  wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    wndclass.lpfnWndProc = WndProc;

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance;

    wndclass.hIcon = LoadIcon(hInstance, szAppName);

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

    wndclass.lpszMenuName = szAppName;

    wndclass.lpszClassName = szAppName;

    if (!RegisterClass(&wndclass))

    {

        MessageBox(NULL, TEXT("This program requires Windows NT!"),

            szAppName, MB_ICONERROR);

        return 0;

    }

    hwnd = CreateWindow(szAppName, NULL,

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT,

        CW_USEDEFAULT, CW_USEDEFAULT,

        NULL, NULL, hInstance, szCmdLine);

    ShowWindow(hwnd, iCmdShow);

    UpdateWindow(hwnd);

    hAccel = LoadAccelerators(hInstance, szAppName);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        if (hDlgModeless == NULL || !IsDialogMessage(hDlgModeless, &msg))

        {

            if (!TranslateAccelerator(hwnd, hAccel, &msg))

            {

                TranslateMessage(&msg);

                DispatchMessage(&msg);

            }

        }

    }

    return msg.wParam;

}

void DoCaption(HWND hwnd, TCHAR* szTitleName)

{

    TCHAR szCaption[64 + MAX_PATH];

    wsprintf(szCaption, TEXT("%s - %s"), szAppName,

        szTitleName[0] ? szTitleName : UNTITLED);

    SetWindowText(hwnd, szCaption);

}

void OkMessage(HWND hwnd, TCHAR* szMessage, TCHAR* szTitleName)

{

    TCHAR szBuffer[64 + MAX_PATH];

    wsprintf(szBuffer, szMessage, szTitleName[0] ? szTitleName : UNTITLED);

    MessageBox(hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION);

}

short AskAboutSave(HWND hwnd, TCHAR* szTitleName)

{

    TCHAR szBuffer[64 + MAX_PATH];

    int   iReturn;

    wsprintf(szBuffer, TEXT("Save current changes in %s?"),

        szTitleName[0] ? szTitleName : UNTITLED);

    iReturn = MessageBox(hwnd, szBuffer, szAppName,

        MB_YESNOCANCEL | MB_ICONQUESTION);

    if (iReturn == IDYES)

        if (!SendMessage(hwnd, WM_COMMAND, ID_FILE_SAVE, 0))

            iReturn = IDCANCEL;

    return iReturn;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

    static BOOL      bNeedSave = FALSE;

    static HINSTANCE hInst;

    static HWND      hwndEdit;

    static int       iOffset;

    static TCHAR     szFileName[MAX_PATH], szTitleName[MAX_PATH];

    static UINT      messageFindReplace;

    int              iSelBeg, iSelEnd, iEnable;

    LPFINDREPLACE    pfr;

    switch (message)

    {

    case WM_CREATE:

        hInst = ((LPCREATESTRUCT)lParam)->hInstance;

        // Create the edit control child window

        hwndEdit = CreateWindow(TEXT("edit"), NULL,

            WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |

            WS_BORDER | ES_LEFT | ES_MULTILINE |

            ES_NOHIDESEL | ES_AUTOHSCROLL | ES_AUTOVSCROLL,

            0, 0, 0, 0,

            hwnd, (HMENU)EDITID, hInst, NULL);

        SendMessage(hwndEdit, EM_LIMITTEXT, 32000, 0L);

        // Initialize common dialog box stuff

        PopFileInitialize(hwnd);

        PopFontInitialize(hwndEdit);

        messageFindReplace = RegisterWindowMessage(FINDMSGSTRING);

        DoCaption(hwnd, szTitleName);

        return 0;

    case WM_SETFOCUS:

        SetFocus(hwndEdit);

        return 0;

    case WM_SIZE:

        MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);

        return 0;

    case WM_INITMENUPOPUP:

        switch (lParam)

        {

        case 1:             // Edit menu

                  // Enable Undo if edit control can do it

            EnableMenuItem((HMENU)wParam, ID_EDIT_UNDO,

                SendMessage(hwndEdit, EM_CANUNDO, 0, 0L) ?

                MF_ENABLED : MF_GRAYED);

            // Enable Paste if text is in the clipboard

            EnableMenuItem((HMENU)wParam, ID_EDIT_PASTE,

                IsClipboardFormatAvailable(CF_TEXT) ?

                MF_ENABLED : MF_GRAYED);

            // Enable Cut, Copy, and Del if text is selected

            SendMessage(hwndEdit, EM_GETSEL, (WPARAM)&iSelBeg,

                (LPARAM)&iSelEnd);

            iEnable = iSelBeg != iSelEnd ? MF_ENABLED : MF_GRAYED;

            EnableMenuItem((HMENU)wParam, ID_EDIT_CUT, iEnable);

            EnableMenuItem((HMENU)wParam, ID_EDIT_COPY, iEnable);

            EnableMenuItem((HMENU)wParam, ID_EDIT_DELETE, iEnable);

            break;

        case 2:             // Search menu

             // Enable Find, Next, and Replace if modeless

             //   dialogs are not already active

            iEnable = hDlgModeless == NULL ?

                MF_ENABLED : MF_GRAYED;

            EnableMenuItem((HMENU)wParam, ID_SEARCH_FIND, iEnable);

            EnableMenuItem((HMENU)wParam, ID_SEARCH_FINDNEXT, iEnable);

            EnableMenuItem((HMENU)wParam, ID_SEARCH_REPLACE, iEnable);

            break;

        }

        return 0;

    case WM_COMMAND:

        // Messages from edit control

        if (lParam && LOWORD(wParam) == EDITID)

        {

            switch (HIWORD(wParam))

            {

            case EN_UPDATE:

                bNeedSave = TRUE;

                return 0;

            case EN_ERRSPACE:

            case EN_MAXTEXT:

                MessageBox(hwnd, TEXT("Edit control out of space."),

                    szAppName, MB_OK | MB_ICONSTOP);

                return 0;

            }

            break;

        }

        switch (LOWORD(wParam))

        {

            // Messages from File menu

        case ID_FILE_NEW:

            if (bNeedSave && IDCANCEL == AskAboutSave(hwnd, szTitleName))

                return 0;

            SetWindowText(hwndEdit, TEXT("\0"));

            szFileName[0] = '\0';

            szTitleName[0] = '\0';

            DoCaption(hwnd, szTitleName);

            bNeedSave = FALSE;

            return 0;

        case ID_FILE_OPEN:

            if (bNeedSave && IDCANCEL == AskAboutSave(hwnd, szTitleName))

                return 0;

            if (PopFileOpenDlg(hwnd, szFileName, szTitleName))

            {

                if (!PopFileRead(hwndEdit, szFileName))

                {

                    OkMessage(hwnd, TEXT("Could not read file %s!"),

                        szTitleName);

                    szFileName[0] = '\0';

                    szTitleName[0] = '\0';

                }

            }

            DoCaption(hwnd, szTitleName);

            bNeedSave = FALSE;

            return 0;

        case ID_FILE_SAVE:

            if (szFileName[0])

            {

                if (PopFileWrite(hwndEdit, szFileName))

                {

                    bNeedSave = FALSE;

                    return 1;

                }

                else

                {

                    OkMessage(hwnd, TEXT("Could not write file %s"),

                        szTitleName);

                    return 0;

                }

            }

            // fall through

        case ID_FILE_SAVEAS:

            if (PopFileSaveDlg(hwnd, szFileName, szTitleName))

            {

                DoCaption(hwnd, szTitleName);

                if (PopFileWrite(hwndEdit, szFileName))

                {

                    bNeedSave = FALSE;

                    return 1;

                }

                else

                {

                    OkMessage(hwnd, TEXT("Could not write file %s"),

                        szTitleName);

                    return 0;

                }

            }

            return 0;

        case ID_FILE_PRINT:

            if (!PopPrntPrintFile(hInst, hwnd, hwndEdit, szTitleName))

                OkMessage(hwnd, TEXT("Could not print file %s"),

                    szTitleName);

            return 0;

        case ID_FILE_EXIT:

            SendMessage(hwnd, WM_CLOSE, 0, 0);

            return 0;

            // Messages from Edit menu

        case ID_EDIT_UNDO:

            SendMessage(hwndEdit, WM_UNDO, 0, 0);

            return 0;

        case ID_EDIT_CUT:

            SendMessage(hwndEdit, WM_CUT, 0, 0);

            return 0;

        case ID_EDIT_COPY:

            SendMessage(hwndEdit, WM_COPY, 0, 0);

            return 0;

        case ID_EDIT_PASTE:

            SendMessage(hwndEdit, WM_PASTE, 0, 0);

            return 0;

        case ID_EDIT_DELETE:

            SendMessage(hwndEdit, WM_CLEAR, 0, 0);

            return 0;

        case ID_EDIT_SELECTALL:

            SendMessage(hwndEdit, EM_SETSEL, 0, -1);

            return 0;

            // Messages from Search menu

        case ID_SEARCH_FIND:

            SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);

            hDlgModeless = PopFindFindDlg(hwnd);

            return 0;

        case ID_SEARCH_FINDNEXT:

            SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);

            if (PopFindValidFind())

                PopFindNextText(hwndEdit, &iOffset);

            else

                hDlgModeless = PopFindFindDlg(hwnd);

            return 0;

        case ID_SEARCH_REPLACE:

            SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);

            hDlgModeless = PopFindReplaceDlg(hwnd);

            return 0;

        case ID_FORMAT_FONT:

            if (PopFontChooseFont(hwnd))

                PopFontSetFont(hwndEdit);

            return 0;

            // Messages from Help menu

        case ID_HELP_HELP:

            OkMessage(hwnd, TEXT("Help not yet implemented!"),

                TEXT("\0"));

            return 0;

        case ID_HELP_ABOUTPOPPAD:

            DialogBox(hInst, TEXT("AboutBox"), hwnd, AboutDlgProc);

            return 0;

        }

        break;

    case WM_CLOSE:

        if (!bNeedSave || IDCANCEL != AskAboutSave(hwnd, szTitleName))

            DestroyWindow(hwnd);

        return 0;

    case WM_QUERYENDSESSION:

        if (!bNeedSave || IDCANCEL != AskAboutSave(hwnd, szTitleName))

            return 1;

        return 0;

    case WM_DESTROY:

        PopFontDeinitialize();

        PostQuitMessage(0);

        return 0;

    default:

        // Process "Find-Replace" messages

        if (message == messageFindReplace)

        {

            pfr = (LPFINDREPLACE)lParam;

            if (pfr->Flags & FR_DIALOGTERM)

                hDlgModeless = NULL;

            if (pfr->Flags & FR_FINDNEXT)

                if (!PopFindFindText(hwndEdit, &iOffset, pfr))

                    OkMessage(hwnd, TEXT("Text not found!"),

                        TEXT("\0"));

            if (pfr->Flags & FR_REPLACE || pfr->Flags & FR_REPLACEALL)

                if (!PopFindReplaceText(hwndEdit, &iOffset, pfr))

                    OkMessage(hwnd, TEXT("Text not found!"),

                        TEXT("\0"));

            if (pfr->Flags & FR_REPLACEALL)

                while (PopFindReplaceText(hwndEdit, &iOffset, pfr));

            return 0;

        }

        break;

    }

    return DefWindowProc(hwnd, message, wParam, lParam);

}

BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT message,

    WPARAM wParam, LPARAM lParam)

{

    switch (message)

    {

    case WM_INITDIALOG:

        return TRUE;

    case WM_COMMAND:

        switch (LOWORD(wParam))

        {

        case IDOK:

            EndDialog(hDlg, 0);

            return TRUE;

        }

        break;

    }

    return FALSE;

}

PpopFile.c

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

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

/*------------------------------------------

   POPFILE.C -- Popup Editor File Functions

  ------------------------------------------*/

static OPENFILENAME ofn ;

void PopFileInitialize (HWND hwnd)

{

     static TCHAR szFilter[] = TEXT ("Text Files (*.TXT)\0*.txt\0")  \

                               TEXT ("ASCII Files (*.ASC)\0*.asc\0") \

                               TEXT ("All Files (*.*)\0*.*\0\0") ;

     ofn.lStructSize       = sizeof (OPENFILENAME) ;

     ofn.hwndOwner         = hwnd ;

     ofn.hInstance         = NULL ;

     ofn.lpstrFilter       = szFilter ;

     ofn.lpstrCustomFilter = NULL ;

     ofn.nMaxCustFilter    = 0 ;

     ofn.nFilterIndex      = 0 ;

     ofn.lpstrFile         = NULL ;          // Set in Open and Close functions

     ofn.nMaxFile          = MAX_PATH ;

     ofn.lpstrFileTitle    = NULL ;          // Set in Open and Close functions

     ofn.nMaxFileTitle     = MAX_PATH ;

     ofn.lpstrInitialDir   = NULL ;

     ofn.lpstrTitle        = NULL ;

     ofn.Flags             = 0 ;             // Set in Open and Close functions

     ofn.nFileOffset       = 0 ;

     ofn.nFileExtension    = 0 ;

     ofn.lpstrDefExt       = TEXT ("txt") ;

     ofn.lCustData         = 0L ;

     ofn.lpfnHook          = NULL ;

     ofn.lpTemplateName    = NULL ;

}

BOOL PopFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)

{

     ofn.hwndOwner         = hwnd ;

     ofn.lpstrFile         = pstrFileName ;

     ofn.lpstrFileTitle    = pstrTitleName ;

     ofn.Flags             = OFN_HIDEREADONLY | OFN_CREATEPROMPT ;

     return GetOpenFileName (&ofn) ;

}

BOOL PopFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)

{

     ofn.hwndOwner         = hwnd ;

     ofn.lpstrFile         = pstrFileName ;

     ofn.lpstrFileTitle    = pstrTitleName ;

     ofn.Flags             = OFN_OVERWRITEPROMPT ;

     return GetSaveFileName (&ofn) ;

}

BOOL PopFileRead (HWND hwndEdit, PTSTR pstrFileName)

{

     BYTE   bySwap ;

     DWORD  dwBytesRead ;

     HANDLE hFile ;

     int    i, iFileLength, iUniTest ;

     PBYTE  pBuffer, pText, pConv ;

          // Open the file.

     if (INVALID_HANDLE_VALUE ==

               (hFile = CreateFile (pstrFileName, GENERIC_READ, FILE_SHARE_READ,

                                    NULL, OPEN_EXISTING, 0, NULL)))

          return FALSE ;

          // Get file size in bytes and allocate memory for read.

          // Add an extra two bytes for zero termination.

     iFileLength = GetFileSize (hFile, NULL) ;

     pBuffer = malloc (iFileLength + 2) ;

          // Read file and put terminating zeros at end.

     ReadFile (hFile, pBuffer, iFileLength, &dwBytesRead, NULL) ;

     CloseHandle (hFile) ;

     pBuffer[iFileLength] = '\0' ;

     pBuffer[iFileLength + 1] = '\0' ;

          // Test to see if the text is Unicode

     iUniTest = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE ;

     if (IsTextUnicode (pBuffer, iFileLength, &iUniTest))

     {

          pText = pBuffer + 2 ;

          iFileLength -= 2 ;

          if (iUniTest & IS_TEXT_UNICODE_REVERSE_SIGNATURE)

          {

               for (i = 0 ; i < iFileLength / 2 ; i++)

               {

                    bySwap = ((BYTE *) pText) [2 * i] ;

                    ((BYTE *) pText) [2 * i] = ((BYTE *) pText) [2 * i + 1] ;

                    ((BYTE *) pText) [2 * i + 1] = bySwap ;

               }

          }

               // Allocate memory for possibly converted string

          pConv = malloc (iFileLength + 2) ;

               // If the edit control is not Unicode, convert Unicode text to

               // non-Unicode (ie, in general, wide character).

          WideCharToMultiByte (CP_ACP, 0, (PWSTR) pText, -1, pConv,

                               iFileLength + 2, NULL, NULL) ;

               // If the edit control is Unicode, just copy the string

          lstrcpy ((PTSTR) pConv, (PTSTR) pText) ;

     }

     else      // the file is not Unicode

     {

          pText = pBuffer ;

               // Allocate memory for possibly converted string.

          pConv = malloc (2 * iFileLength + 2) ;

               // If the edit control is Unicode, convert ASCII text.

          MultiByteToWideChar (CP_ACP, 0, pText, -1, (PTSTR) pConv,

                               iFileLength + 1) ;

               // If not, just copy buffer

          lstrcpy ((PTSTR) pConv, (PTSTR) pText) ;

     }

     SetWindowText (hwndEdit, (PTSTR) pConv) ;

     free (pBuffer) ;

     free (pConv) ;

     return TRUE ;

}

BOOL PopFileWrite (HWND hwndEdit, PTSTR pstrFileName)

{

     DWORD  dwBytesWritten ;

     HANDLE hFile ;

     int    iLength ;

     PTSTR  pstrBuffer ;

     WORD   wByteOrderMark = 0xFEFF ;

          // Open the file, creating it if necessary

     if (INVALID_HANDLE_VALUE ==

               (hFile = CreateFile (pstrFileName, GENERIC_WRITE, 0,

                                    NULL, CREATE_ALWAYS, 0, NULL)))

          return FALSE ;

          // Get the number of characters in the edit control and allocate

          // memory for them.

     iLength = GetWindowTextLength (hwndEdit) ;

     pstrBuffer = (PTSTR) malloc ((iLength + 1) * sizeof (TCHAR)) ;

     if (!pstrBuffer)

     {

          CloseHandle (hFile) ;

          return FALSE ;

     }

          // If the edit control will return Unicode text, write the

          // byte order mark to the file.

     WriteFile (hFile, &wByteOrderMark, 2, &dwBytesWritten, NULL) ;

          // Get the edit buffer and write that out to the file.

     GetWindowText (hwndEdit, pstrBuffer, iLength + 1) ;

     WriteFile (hFile, pstrBuffer, iLength * sizeof (TCHAR),

                &dwBytesWritten, NULL) ;

     if ((iLength * sizeof (TCHAR)) != (int) dwBytesWritten)

     {

          CloseHandle (hFile) ;

          free (pstrBuffer) ;

          return FALSE ;

     }

     CloseHandle (hFile) ;

     free (pstrBuffer) ;

     return TRUE ;

}

PopFind.c

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

/*--------------------------------------------------------

   POPFIND.C -- Popup Editor Search and Replace Functions

  --------------------------------------------------------*/

static TCHAR szFindText [MAX_STRING_LEN] ;

static TCHAR szReplText [MAX_STRING_LEN] ;

HWND PopFindFindDlg (HWND hwnd)

{

     static FINDREPLACE fr ;       // must be static for modeless dialog!!!

     fr.lStructSize      = sizeof (FINDREPLACE) ;

     fr.hwndOwner        = hwnd ;

     fr.hInstance        = NULL ;

     fr.Flags            = FR_HIDEUPDOWN | FR_HIDEMATCHCASE | FR_HIDEWHOLEWORD ;

     fr.lpstrFindWhat    = szFindText ;

     fr.lpstrReplaceWith = NULL ;

     fr.wFindWhatLen     = MAX_STRING_LEN ;

     fr.wReplaceWithLen  = 0 ;

     fr.lCustData        = 0 ;

     fr.lpfnHook         = NULL ;

     fr.lpTemplateName   = NULL ;

     return FindText (&fr) ;

}

HWND PopFindReplaceDlg (HWND hwnd)

{

     static FINDREPLACE fr ;       // must be static for modeless dialog!!!

     fr.lStructSize      = sizeof (FINDREPLACE) ;

     fr.hwndOwner        = hwnd ;

     fr.hInstance        = NULL ;

     fr.Flags            = FR_HIDEUPDOWN | FR_HIDEMATCHCASE | FR_HIDEWHOLEWORD ;

     fr.lpstrFindWhat    = szFindText ;

     fr.lpstrReplaceWith = szReplText ;

     fr.wFindWhatLen     = MAX_STRING_LEN ;

     fr.wReplaceWithLen  = MAX_STRING_LEN ;

     fr.lCustData        = 0 ;

     fr.lpfnHook         = NULL ;

     fr.lpTemplateName   = NULL ;

     return ReplaceText (&fr) ;

}

BOOL PopFindFindText (HWND hwndEdit, int * piSearchOffset, LPFINDREPLACE pfr)

{

     int    iLength, iPos ;

     PTSTR  pstrDoc, pstrPos ;

          // Read in the edit document

     iLength = GetWindowTextLength (hwndEdit) ;

     if (NULL == (pstrDoc = (PTSTR) malloc ((iLength + 1) * sizeof (TCHAR))))

          return FALSE ;

     GetWindowText (hwndEdit, pstrDoc, iLength + 1) ;

          // Search the document for the find string

     pstrPos = _tcsstr (pstrDoc + * piSearchOffset, pfr->lpstrFindWhat) ;

     free (pstrDoc) ;

          // Return an error code if the string cannot be found

     if (pstrPos == NULL)

          return FALSE ;

          // Find the position in the document and the new start offset

     iPos = pstrPos - pstrDoc ;

     * piSearchOffset = iPos + lstrlen (pfr->lpstrFindWhat) ;

          // Select the found text

     SendMessage (hwndEdit, EM_SETSEL, iPos, * piSearchOffset) ;

     SendMessage (hwndEdit, EM_SCROLLCARET, 0, 0) ;

     return TRUE ;

}

BOOL PopFindNextText (HWND hwndEdit, int * piSearchOffset)

{

     FINDREPLACE fr ;

     fr.lpstrFindWhat = szFindText ;

     return PopFindFindText (hwndEdit, piSearchOffset, &fr) ;

}

BOOL PopFindReplaceText (HWND hwndEdit, int * piSearchOffset, LPFINDREPLACE pfr)

{

          // Find the text

     if (!PopFindFindText (hwndEdit, piSearchOffset, pfr))

          return FALSE ;

          // Replace it

     SendMessage (hwndEdit, EM_REPLACESEL, 0, (LPARAM) pfr->lpstrReplaceWith) ;

     return TRUE ;

}

BOOL PopFindValidFind (void)

{

     return * szFindText != '\0' ;

}

PopFont.c

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

/*------------------------------------------

   POPFONT.C -- Popup Editor Font Functions

  ------------------------------------------*/

static LOGFONT logfont ;

static HFONT   hFont ;

BOOL PopFontChooseFont (HWND hwnd)

{

     CHOOSEFONT cf ;

     cf.lStructSize    = sizeof (CHOOSEFONT) ;

     cf.hwndOwner      = hwnd ;

     cf.hDC            = NULL ;

     cf.lpLogFont      = &logfont ;

     cf.iPointSize     = 0 ;

     cf.Flags          = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS | CF_EFFECTS ;

     cf.rgbColors      = 0 ;

     cf.lCustData      = 0 ;

     cf.lpfnHook       = NULL ;

     cf.lpTemplateName = NULL ;

     cf.hInstance      = NULL ;

     cf.lpszStyle      = NULL ;

     cf.nFontType      = 0 ;               // Returned from ChooseFont

     cf.nSizeMin       = 0 ;

     cf.nSizeMax       = 0 ;

     return ChooseFont (&cf) ;

}

void PopFontInitialize (HWND hwndEdit)

{

     GetObject (GetStockObject (SYSTEM_FONT), sizeof (LOGFONT),

                (PTSTR) &logfont) ;

     hFont = CreateFontIndirect (&logfont) ;

     SendMessage (hwndEdit, WM_SETFONT, (WPARAM) hFont, 0) ;

}

void PopFontSetFont (HWND hwndEdit)

{

     HFONT hFontNew ;

     RECT  rect ;

     hFontNew = CreateFontIndirect (&logfont) ;

     SendMessage (hwndEdit, WM_SETFONT, (WPARAM) hFontNew, 0) ;

     DeleteObject (hFont) ;

     hFont = hFontNew ;

     GetClientRect (hwndEdit, &rect) ;

     InvalidateRect (hwndEdit, &rect, TRUE) ;

}

void PopFontDeinitialize (void)

{

     DeleteObject (hFont) ;

}

PopPrnt0.c

1

2

3

4

5

6

7

8

9

10

11

/*---------------------------------------------------------------

   POPPRNT0.C -- Popup Editor Printing Functions (dummy version)

  ---------------------------------------------------------------*/

BOOL PopPrntPrintFile (HINSTANCE hInst, HWND hwnd, HWND hwndEdit,

                       PTSTR pstrTitleName)

{

     return FALSE ;

}

[2022冬季班]《安卓高级研修班(网课)》月薪三万班招生中~

最后于 2022-12-15 22:14 被zhang_derek编辑 ,原因:


文章来源: https://bbs.pediy.com/thread-275547.htm
如有侵权请联系:admin#unsafe.sh