上学期学习数据结构的时候,我做了一个多项式加法的演示程序,演示教材中用链表实现的多项式加法。
可以单步跟踪,一步一步的看效果,也可以流水执行,整体浏览。
每一步执行都有图像显示当前链表的情况。
正在执行的代码行会高亮显示。
纯粹的 C 语言使用 Win32 API ,没有使用资源。
先贴两个截图:
主控窗口如下,
工作的时候,如下
贴一下源代码:
Calc.h
1#ifndef __CALC_H
2#define __CALC_H
3
4
5#include "Poly.h"
6
7
8#define CALC_TO_STR_BUF_LEN 100
9#define TIME_WAIT_RETRY 200
10#define TIME_DISP_NEW 1000
11
12#define CHECK(i) \
13 if ( ( fRun == CALC_STATE_RUN_INIT ) || ( fCalc == CALC_STATE_CALC_INIT ) ) { \
14 Sleep( TIME_WAIT_RETRY ); \
15 goto i; \
16 } \
17 while ( ( fCalc != CALC_STATE_CALC_CALC ) && ( fRun != CALC_STATE_RUN_INIT ) && ( fCalc != CALC_STATE_CALC_INIT ) ) { \
18 Sleep( TIME_WAIT_RETRY ); \
19 } \
20 if ( ( fRun == CALC_STATE_RUN_INIT ) || ( fCalc == CALC_STATE_CALC_INIT ) ) { \
21 goto i; \
22 }
23#define CK CHECK( START )
24
25#define CTRL(i) SendMessage( hCtrlWnd, WM_MY_NOTIFY, MY_NOTIFY_CTRL_WND_CALCED, i )
26#define CT CTRL( 0 )
27
28#define DISP(i) SendMessage( hDispWnd, WM_MY_NOTIFY, MY_NOTIFY_DISP_WND_STEP, i )
29#define DISP_LAST DISP( MY_NOTIFY_LPARAM_OUT_LAST )
30#define DISP_FIRST DISP( MY_NOTIFY_LPARAM_BLANK_FIRST )
31#define DISP_NORMAL DISP( 0 )
32#define DISP_NEW DISP_LAST; Sleep( TIME_DISP_NEW ); DISP_NORMAL
33
34#define CODE(i) SendMessage( hCodeWnd, WM_MY_NOTIFY, MY_NOTIFY_CODE_WND_STEP, i )
35
36#define CD(i) CT; CK; CODE( i )
37#define CDN(i) CT; DISP_NEW; CK; CODE( i )
38#define CDS(i) CT; DISP_NORMAL; CK; CODE( i )
39#define CDE(i) CT; DISP_FIRST; Sleep( TIME_DISP_NEW ); DISP_NORMAL; CK; CODE( i )
40
41
42#endif
43
CodeWnd.h
1#ifndef __CODE_WND_H
2#define __CODE_WND_H
3
4
5#include "Poly.h"
6
7
8#define CODE_LINE \
9TEXT( " \r\n" ) \
10TEXT( "struct node \r\n" ) \
11TEXT( "{ \r\n" ) \
12TEXT( " int coef, exp; \r\n" ) \
13TEXT( " struct node * link; \r\n" ) \
14TEXT( "}; \r\n" ) \
15TEXT( "typedef struct node NODE; \r\n" ) \
16TEXT( " \r\n" ) \
17TEXT( "NODE * insert( NODE * p, int c, int e ) { \r\n" ) \
18TEXT( " NODE * t = (NODE*)malloc( sizeof( NODE ) );\r\n" ) \
19TEXT( " t->coef = c; \r\n" ) \
20TEXT( " t->exp = e; \r\n" ) \
21TEXT( " t->link = 0; \r\n" ) \
22TEXT( " p->link = t; \r\n" ) \
23TEXT( " return t; \r\n" ) \
24TEXT( "} \r\n" ) \
25TEXT( " \r\n" ) \
26TEXT( "NODE * poly_add1( NODE * ah, NODE * bh ) { \r\n" ) \
27TEXT( " NODE *pa, *pb, *ch, *pc; \r\n" ) \
28TEXT( " char c; \r\n" ) \
29TEXT( " \r\n" ) \
30TEXT( " ch = (NODE*)malloc( sizeof( NODE ) ); \r\n" ) \
31TEXT( " ch->link = 0; \r\n" ) \
32TEXT( " ch->coef = 0; \r\n" ) \
33TEXT( " ch->exp = 0; \r\n" ) \
34TEXT( " pc = ch; \r\n" ) \
35TEXT( " pa = ah; \r\n" ) \
36TEXT( " pb = bh; \r\n" ) \
37TEXT( " \r\n" ) \
38TEXT( " while ( pa && pb ) { \r\n" ) \
39TEXT( " if ( pa->exp == pb->exp ) \r\n" ) \
40TEXT( " c = '='; \r\n" ) \
41TEXT( " else if ( pa->exp > pb->exp ) \r\n" ) \
42TEXT( " c = '>'; \r\n" ) \
43TEXT( " else \r\n" ) \
44TEXT( " c = '<'; \r\n" ) \
45TEXT( " \r\n" ) \
46TEXT( " switch ( c ) { \r\n" ) \
47TEXT( " case '=' : \r\n" ) \
48TEXT( " if ( pa->coef + pb->coef ) \r\n" ) \
49TEXT( " pc = insert( pc, \r\n" ) \
50TEXT( " pa->coef + pb->coef, \r\n" ) \
51TEXT( " pa->exp ); \r\n" ) \
52TEXT( " pa = pa->link; \r\n" ) \
53TEXT( " pb = pb->link; \r\n" ) \
54TEXT( " break; \r\n" ) \
55TEXT( " case '>' : \r\n" ) \
56TEXT( " pc = insert( pc, \r\n" ) \
57TEXT( " pa->coef, \r\n" ) \
58TEXT( " pa->exp ); \r\n" ) \
59TEXT( " pa = pa->link; \r\n" ) \
60TEXT( " break; \r\n" ) \
61TEXT( " case '<' : \r\n" ) \
62TEXT( " pc = insert( pc, \r\n" ) \
63TEXT( " pb->coef, \r\n" ) \
64TEXT( " pb->exp ); \r\n" ) \
65TEXT( " pb = pb->link; \r\n" ) \
66TEXT( " break; \r\n" ) \
67TEXT( " } \r\n" ) \
68TEXT( " } \r\n" ) \
69TEXT( " \r\n" ) \
70TEXT( " while ( pa ) { \r\n" ) \
71TEXT( " pc = insert( pc, \r\n" ) \
72TEXT( " pa->coef, \r\n" ) \
73TEXT( " pa->exp ); \r\n" ) \
74TEXT( " pa = pa->link; \r\n" ) \
75TEXT( " } \r\n" ) \
76TEXT( " \r\n" ) \
77TEXT( " while ( pb ) { \r\n" ) \
78TEXT( " pc = insert( pc, \r\n" ) \
79TEXT( " pb->coef, \r\n" ) \
80TEXT( " pb->exp ); \r\n" ) \
81TEXT( " pb = pb->link; \r\n" ) \
82TEXT( " } \r\n" ) \
83TEXT( " \r\n" ) \
84TEXT( " pc->link = 0; \r\n" ) \
85TEXT( " pc = ch; \r\n" ) \
86TEXT( " if ( ch->link ) { \r\n" ) \
87TEXT( " ch = ch->link; \r\n" ) \
88TEXT( " free( pc ); \r\n" ) \
89TEXT( " } \r\n" ) \
90TEXT( " return ch; \r\n" ) \
91TEXT( "} \r\n" ) \
92TEXT( " \r\n" )
93
94#define CODE_WND_EDIT_ID_CODE_LINE 201
95
96
97#endif
98
CtrlWnd.h
1#ifndef __CTRL_WND_H
2#define __CTRL_WND_H
3
4
5#include "Poly.h"
6
7
8#define CTRL_WND_CLIENT_WIDTH ( CTRL_WND_WIDTH - 10 )
9#define CTRL_WND_CLIENT_HEIGHT ( CTRL_WND_HEIGHT - 50 )
10#define CTRL_WND_DELTA 10
11#define CTRL_WND_EXP_WIDTH_RAT 0.75
12
13#define CTRL_WND_EXP_POS_X CTRL_WND_DELTA
14#define CTRL_WND_EXP_POS_Y CTRL_WND_DELTA
15#define CTRL_WND_EXP_WIDTH ( (int)( ( CTRL_WND_CLIENT_WIDTH - CTRL_WND_DELTA * 3 ) * CTRL_WND_EXP_WIDTH_RAT ) )
16#define CTRL_WND_EXP_HEIGHT ( CTRL_WND_CLIENT_HEIGHT - CTRL_WND_DELTA - CTRL_WND_EXP_POS_Y )
17#define CTRL_WND_EXP_NOTE_WIDTH_RAT 0.05
18
19#define CTRL_WND_EXP_NOTE_A_POS_X ( CTRL_WND_EXP_POS_X + CTRL_WND_DELTA )
20#define CTRL_WND_EXP_NOTE_A_POS_Y ( CTRL_WND_EXP_POS_Y + CTRL_WND_DELTA * 2 )
21#define CTRL_WND_EXP_NOTE_A_WIDTH ( (int)( ( CTRL_WND_EXP_WIDTH - CTRL_WND_DELTA * 2 ) * CTRL_WND_EXP_NOTE_WIDTH_RAT ) )
22#define CTRL_WND_EXP_NOTE_A_HEIGHT ( ( CTRL_WND_EXP_POS_Y + CTRL_WND_EXP_HEIGHT - CTRL_WND_EXP_NOTE_A_POS_Y - CTRL_WND_DELTA * 4 ) / 4 )
23
24#define CTRL_WND_EXP_EDIT_A_POS_X ( CTRL_WND_EXP_NOTE_A_POS_X + CTRL_WND_EXP_NOTE_A_WIDTH )
25#define CTRL_WND_EXP_EDIT_A_POS_Y CTRL_WND_EXP_NOTE_A_POS_Y
26#define CTRL_WND_EXP_EDIT_A_WIDTH ( CTRL_WND_EXP_WIDTH - CTRL_WND_DELTA * 2 - CTRL_WND_EXP_NOTE_A_WIDTH )
27#define CTRL_WND_EXP_EDIT_A_HEIGHT CTRL_WND_EXP_NOTE_A_HEIGHT
28
29#define CTRL_WND_EXP_NOTE_B_POS_X CTRL_WND_EXP_NOTE_A_POS_X
30#define CTRL_WND_EXP_NOTE_B_POS_Y ( CTRL_WND_EXP_NOTE_A_POS_Y + CTRL_WND_EXP_NOTE_A_HEIGHT + CTRL_WND_DELTA )
31#define CTRL_WND_EXP_NOTE_B_WIDTH CTRL_WND_EXP_NOTE_A_WIDTH
32#define CTRL_WND_EXP_NOTE_B_HEIGHT CTRL_WND_EXP_NOTE_A_HEIGHT
33
34#define CTRL_WND_EXP_EDIT_B_POS_X CTRL_WND_EXP_EDIT_A_POS_X
35#define CTRL_WND_EXP_EDIT_B_POS_Y CTRL_WND_EXP_NOTE_B_POS_Y
36#define CTRL_WND_EXP_EDIT_B_WIDTH CTRL_WND_EXP_EDIT_A_WIDTH
37#define CTRL_WND_EXP_EDIT_B_HEIGHT CTRL_WND_EXP_EDIT_A_HEIGHT
38
39#define CTRL_WND_EXP_NOTE_C_POS_X CTRL_WND_EXP_NOTE_B_POS_X
40#define CTRL_WND_EXP_NOTE_C_POS_Y ( CTRL_WND_EXP_NOTE_B_POS_Y + CTRL_WND_EXP_NOTE_B_HEIGHT + CTRL_WND_DELTA )
41#define CTRL_WND_EXP_NOTE_C_WIDTH CTRL_WND_EXP_NOTE_B_WIDTH
42#define CTRL_WND_EXP_NOTE_C_HEIGHT CTRL_WND_EXP_NOTE_B_HEIGHT
43
44#define CTRL_WND_EXP_EDIT_C_POS_X CTRL_WND_EXP_EDIT_B_POS_X
45#define CTRL_WND_EXP_EDIT_C_POS_Y CTRL_WND_EXP_NOTE_C_POS_Y
46#define CTRL_WND_EXP_EDIT_C_WIDTH CTRL_WND_EXP_EDIT_B_WIDTH
47#define CTRL_WND_EXP_EDIT_C_HEIGHT CTRL_WND_EXP_EDIT_B_HEIGHT
48
49#define CTRL_WND_EXP_CLEAR_STOP_POS_X CTRL_WND_EXP_EDIT_C_POS_X
50#define CTRL_WND_EXP_CLEAR_STOP_POS_Y ( CTRL_WND_EXP_EDIT_C_POS_Y + CTRL_WND_EXP_EDIT_C_HEIGHT + CTRL_WND_DELTA )
51#define CTRL_WND_EXP_CLEAR_STOP_WIDTH ( ( CTRL_WND_EXP_EDIT_C_WIDTH - CTRL_WND_DELTA * 5 ) / 2 )
52#define CTRL_WND_EXP_CLEAR_STOP_HEIGHT CTRL_WND_EXP_EDIT_C_HEIGHT
53
54#define CTRL_WND_EXP_START_CONTINUE_POS_X ( CTRL_WND_EXP_CLEAR_STOP_POS_X + CTRL_WND_EXP_CLEAR_STOP_WIDTH + CTRL_WND_DELTA * 5 )
55#define CTRL_WND_EXP_START_CONTINUE_POS_Y CTRL_WND_EXP_CLEAR_STOP_POS_Y
56#define CTRL_WND_EXP_START_CONTINUE_WIDTH CTRL_WND_EXP_CLEAR_STOP_WIDTH
57#define CTRL_WND_EXP_START_CONTINUE_HEIGHT CTRL_WND_EXP_CLEAR_STOP_HEIGHT
58
59#define CTRL_WND_VIEW_POS_X ( CTRL_WND_EXP_POS_X + CTRL_WND_EXP_WIDTH + CTRL_WND_DELTA )
60#define CTRL_WND_VIEW_POS_Y CTRL_WND_EXP_POS_Y
61#define CTRL_WND_VIEW_WIDTH ( CTRL_WND_CLIENT_WIDTH - CTRL_WND_VIEW_POS_X - CTRL_WND_DELTA )
62#define CTRL_WND_VIEW_HEIGHT ( ( CTRL_WND_EXP_HEIGHT - CTRL_WND_DELTA ) / 2 )
63
64#define CTRL_WND_VIEW_CODE_POS_X ( CTRL_WND_VIEW_POS_X + CTRL_WND_DELTA )
65#define CTRL_WND_VIEW_CODE_POS_Y ( CTRL_WND_VIEW_POS_Y + CTRL_WND_DELTA )
66#define CTRL_WND_VIEW_CODE_WIDTH ( CTRL_WND_VIEW_WIDTH - CTRL_WND_DELTA * 2 )
67#define CTRL_WND_VIEW_CODE_HEIGHT ( ( CTRL_WND_VIEW_HEIGHT - CTRL_WND_DELTA * 3 ) / 2 )
68
69#define CTRL_WND_VIEW_DISP_POS_X CTRL_WND_VIEW_CODE_POS_X
70#define CTRL_WND_VIEW_DISP_POS_Y ( CTRL_WND_VIEW_CODE_POS_Y + CTRL_WND_VIEW_CODE_HEIGHT + CTRL_WND_DELTA )
71#define CTRL_WND_VIEW_DISP_WIDTH CTRL_WND_VIEW_CODE_WIDTH
72#define CTRL_WND_VIEW_DISP_HEIGHT CTRL_WND_VIEW_CODE_HEIGHT
73
74#define CTRL_WND_RUN_POS_X CTRL_WND_VIEW_POS_X
75#define CTRL_WND_RUN_POS_Y ( CTRL_WND_VIEW_POS_Y + CTRL_WND_VIEW_HEIGHT + CTRL_WND_DELTA )
76#define CTRL_WND_RUN_WIDTH CTRL_WND_VIEW_WIDTH
77#define CTRL_WND_RUN_HEIGHT CTRL_WND_VIEW_HEIGHT
78
79#define CTRL_WND_RUN_STEP_POS_X ( CTRL_WND_RUN_POS_X + CTRL_WND_DELTA )
80#define CTRL_WND_RUN_STEP_POS_Y ( CTRL_WND_RUN_POS_Y + CTRL_WND_DELTA )
81#define CTRL_WND_RUN_STEP_WIDTH ( CTRL_WND_RUN_WIDTH - CTRL_WND_DELTA * 2 )
82#define CTRL_WND_RUN_STEP_HEIGHT ( ( CTRL_WND_RUN_HEIGHT - CTRL_WND_DELTA * 3 ) / 2 )
83
84#define CTRL_WND_RUN_PIPELINE_POS_X CTRL_WND_RUN_STEP_POS_X
85#define CTRL_WND_RUN_PIPELINE_POS_Y ( CTRL_WND_RUN_STEP_POS_Y + CTRL_WND_RUN_STEP_HEIGHT + CTRL_WND_DELTA )
86#define CTRL_WND_RUN_PIPELINE_WIDTH CTRL_WND_RUN_STEP_WIDTH
87#define CTRL_WND_RUN_PIPELINE_HEIGHT CTRL_WND_RUN_STEP_HEIGHT
88
89#define CTRL_WND_MENU_ID_EXIT 101
90#define CTRL_WND_BUTTON_ID_EXP 102
91#define CTRL_WND_BUTTON_ID_VIEW 103
92#define CTRL_WND_BUTTON_ID_RUN 104
93#define CTRL_WND_BUTTON_ID_VIEW_CODE 105
94#define CTRL_WND_BUTTON_ID_VIEW_DISP 106
95#define CTRL_WND_BUTTON_ID_RUN_STEP 107
96#define CTRL_WND_BUTTON_ID_RUN_PIPELINE 108
97#define CTRL_WND_BUTTON_ID_EXP_CLEAR_STOP 109
98#define CTRL_WND_BUTTON_ID_EXP_START_CONTINUE 110
99#define CTRL_WND_EDIT_ID_A 111
100#define CTRL_WND_NOTE_ID_A 112
101#define CTRL_WND_EDIT_ID_B 113
102#define CTRL_WND_NOTE_ID_B 114
103#define CTRL_WND_EDIT_ID_C 115
104#define CTRL_WND_NOTE_ID_C 116
105#define CTRL_WND_TIMER_ID_DELTA 117
106
107#define CTRL_WND_DELTA_TIME 2000
108#define CTRL_WND_DELTA_TIME_PIECE 10
109
110
111#endif
112
DispWnd.h
1#ifndef __DISP_WND_H
2#define __DISP_WND_H
3
4
5#include "Poly.h"
6
7
8#define NODE_PEN_WIDTH 3
9#define NODE_PEN_COLOR RGB( 0, 0, 255 )
10
11#define NODE_WIDTH_COEF 70
12#define NODE_WIDTH_EXP 50
13#define NODE_WIDTH_LINK 30
14#define NODE_WIDTH_DIST 30
15#define NODE_WIDTH ( NODE_WIDTH_COEF + NODE_WIDTH_EXP + NODE_WIDTH_LINK )
16#define NODE_WIDTH_UNIT ( NODE_WIDTH + NODE_WIDTH_DIST )
17
18#define NODE_HEIGHT 50
19#define NODE_HEIGHT_DIST 70
20#define NODE_HEIGHT_UNIT ( NODE_HEIGHT + NODE_HEIGHT_DIST )
21
22#define NODE_WIDTH_HEADER 50
23
24#define NODE_POINTER_HEIGHT NODE_HEIGHT
25#define NODE_POINTER_HEIGHT_DIST ( ( NODE_HEIGHT_UNIT - NODE_HEIGHT - NODE_POINTER_HEIGHT ) / 2 )
26
27#define NODE_ORG_POS_X 20
28#define NODE_ORG_POS_Y 20
29
30
31#endif
32
Poly.h
1#ifndef __POLY_H
2#define __POLY_H
3
4
5#include <Windows.h>
6
7
8#define CTRL_WND_POS_X 0
9#define CTRL_WND_POS_Y 0
10#define CTRL_WND_WIDTH 800
11#define CTRL_WND_HEIGHT 300
12
13#define CODE_WND_POS_X ( CTRL_WND_POS_X + CTRL_WND_WIDTH )
14#define CODE_WND_POS_Y CTRL_WND_POS_Y
15#define CODE_WND_WIDTH ( GetSystemMetrics( SM_CXSCREEN ) - CODE_WND_POS_X )
16#define CODE_WND_HEIGHT ( GetSystemMetrics( SM_CYSCREEN ) - 50 )
17
18#define DISP_WND_POS_X CTRL_WND_POS_X
19#define DISP_WND_POS_Y ( CTRL_WND_POS_Y + CTRL_WND_HEIGHT )
20#define DISP_WND_WIDTH ( CTRL_WND_WIDTH + CODE_WND_WIDTH )
21#define DISP_WND_HEIGHT ( CODE_WND_HEIGHT - DISP_WND_POS_Y )
22
23#define CALC_STATE_RUN_INIT 10
24#define CALC_STATE_RUN_STEP 11
25#define CALC_STATE_RUN_PIPELINE 12
26
27#define CALC_STATE_CALC_INIT 20
28#define CALC_STATE_CALC_WAIT 21
29#define CALC_STATE_CALC_CALC 22
30#define CALC_STATE_CALC_SLEEP 23
31
32#define WM_MY_NOTIFY ( WM_USER + 100 )
33
34#define MY_NOTIFY_CTRL_WND_CALCED 30
35#define MY_NOTIFY_CTRL_WND_CALC_OVER 31
36#define MY_NOTIFY_CTRL_WND_DISP_CLOSE 32
37#define MY_NOTIFY_CTRL_WND_CODE_CLOSE 33
38
39#define MY_NOTIFY_CODE_WND_INIT 40
40#define MY_NOTIFY_CODE_WND_STEP 41
41/**//* on MY_NOTIFY_CODE_WND_STEP, lParam <==> index of line */
42
43#define MY_NOTIFY_DISP_WND_INIT 50
44#define MY_NOTIFY_DISP_WND_STEP 51
45#define MY_NOTIFY_LPARAM_BLANK_FIRST 52
46#define MY_NOTIFY_LPARAM_OUT_LAST 53
47#define MY_NOTIFY_LPARAM_PRED 54
48
49#define MAX_EXP_SZ_LEN 10000
50
51#define FONT_HEIGHT 30
52#define FONT_WEIGHT FW_BOLD
53
54
55struct node
56{
57 INT coef, exp;
58 struct node * link;
59};
60typedef struct node NODE;
61
62
63extern HINSTANCE hInst;
64extern HWND hCtrlWnd, hDispWnd, hCodeWnd;
65extern INT fRun, fCalc;
66extern NODE *ah, *bh, *ch, *pa, *pb, *pc;
67extern HFONT hFont;
68extern TCHAR szExpA[ MAX_EXP_SZ_LEN ], szExpB[ MAX_EXP_SZ_LEN ], szExpC[ MAX_EXP_SZ_LEN ];
69
70// return 0 <==> SUCCEEDED
71INT CtrlWndInit( VOID );
72INT DispWndInit( VOID );
73INT CodeWndInit( VOID );
74INT CalcParse( PCTSTR, NODE ** );
75INT CalcToStr( NODE *, PTSTR, INT );
76
77unsigned int __stdcall Calc( void * );
78VOID CalcInit( VOID );
79
80
81#endif
82
Calc.c
1#include "Calc.h"
2
3
4VOID CalcFreeList( NODE * p ) {
5 NODE * t;
6 while ( p ) {
7 t = p;
8 p = p->link;
9 free( t );
10 }
11}
12
13VOID CalcFreePoly( NODE ** p, NODE ** f ) {
14 CalcFreeList( *p );
15 *p = 0;
16 *f = (NODE*)(1);
17}
18
19VOID CalcInit( VOID ) {
20 CalcFreePoly( &ah, &pa );
21 CalcFreePoly( &bh, &pb );
22 CalcFreePoly( &ch, &pc );
23 SendMessage( hDispWnd, WM_MY_NOTIFY, MY_NOTIFY_DISP_WND_INIT, 0 );
24 SendMessage( hCodeWnd, WM_MY_NOTIFY, MY_NOTIFY_CODE_WND_INIT, 0 );
25}
26
27/**//* 若输入参数不合法,会访问非法,内存泄露 */
28NODE * CalcInsert( NODE * p, INT c, INT e ) {
29 /**//*
30 多线程环境下,为保证对 p 的修改为原子操作使用临时变量 t,
31 虽然不能完全保证,但这里忽略小概率。
32 */
33 NODE * t = (NODE*)malloc( sizeof( NODE ) );
34 t->coef = c;
35 t->exp = e;
36 t->link = 0;
37 p->link = t;
38 return t;
39}
40
41/**//* 若失败,先释放空间,设置空链表 */
42INT CalcParse( PCTSTR psz, NODE ** ppNode ) {
43 PCTSTR presz;
44 NODE *pHead, *pTail;
45 INT sgn, c, e;
46
47 if ( ( psz == 0 ) || ( *psz == 0 ) || ( ppNode == 0 ) )
48 return 1;
49 pHead = pTail = (NODE*)malloc( sizeof( NODE ) );
50 pTail->link = 0;
51
52 while ( *psz ) {
53 if ( ( *psz != TEXT( '+' ) ) && ( *psz != TEXT( '-' ) ) && ( *psz != TEXT( 'x' ) ) && ( ( *psz < TEXT( '0' ) ) || ( *psz > TEXT( '9' ) ) ) ) {
54 CalcFreeList( pHead );
55 return 1;
56 }
57 sgn = 1;
58 if ( *psz == TEXT( '+' ) ) {
59 ++psz;
60 }
61 else if ( *psz == TEXT( '-' ) ) {
62 sgn = -1;
63 ++psz;
64 }
65
66 if ( ( *psz != TEXT( 'x' ) ) && ( ( *psz < TEXT( '0' ) ) || ( *psz > TEXT( '9' ) ) ) ) {
67 CalcFreeList( pHead );
68 return 1;
69 }
70 c = 0;
71 presz = psz;
72 while ( ( *psz >= TEXT( '0' ) ) && ( *psz <= TEXT( '9' ) ) ) {
73 c = c * 10 + (*psz++) - TEXT( '0' );
74 }
75 c = ( presz == psz ? sgn : sgn * c );
76
77 if ( ( *psz != TEXT( 'x' ) ) && ( *psz != 0 ) ) {
78 CalcFreeList( pHead );
79 return 1;
80 }
81 if ( *psz == 0 ) {
82 e = 0;
83 }
84 else {
85 ++psz;
86 if ( *psz != TEXT( '^' ) ) {
87 e = 1;
88 }
89 else {
90 ++psz;
91 if ( ( *psz < TEXT( '0' ) ) || ( *psz > TEXT( '9' ) ) ) {
92 CalcFreeList( pHead );
93 return 1;
94 }
95 e = 0;
96 while ( ( *psz >= TEXT( '0' ) ) && ( *psz <= TEXT( '9' ) ) ) {
97 e = e * 10 + (*psz++) - TEXT( '0' );
98 }
99 }
100 }
101 pTail = CalcInsert( pTail, c, e );
102 }
103 *ppNode = pHead->link;
104 free( pHead );
105 return 0;
106}
107
108INT CalcToStr( NODE * p, PTSTR sz, INT len ) {
109 TCHAR buf[ CALC_TO_STR_BUF_LEN ];
110 INT i = 0, lb;
111
112 if ( ( p == 0 ) || ( sz == 0 ) || ( len < 1 ) )
113 return 1;
114 while ( p ) {
115 lb = wsprintf( buf, TEXT( "%dx^%d" ), p->coef, p->exp );
116 if ( buf[ 0 ] != TEXT( '-' ) ) {
117 ++lb;
118 if ( i + lb >= len )
119 return 1;
120 wsprintf( sz + i, TEXT( "+%dx^%d" ), p->coef, p->exp );
121 i += lb;
122 }
123 else {
124 if ( i + lb >= len )
125 return 1;
126 wsprintf( sz + i, TEXT( "%dx^%d" ), p->coef, p->exp );
127 i += lb;
128 }
129 p = p->link;
130 }
131 sz[ i ] = 0; /**//* 注意多项式 ch 变短 */
132 return 0;
133}
134
135unsigned int __stdcall Calc( void * pParam ) {
136 /**//*
137 多线程环境下,为保证对 ch 的修改为原子操作使用临时变量 pt,
138 虽然不能完全保证,但这里忽略小概率。
139 */
140 NODE * pt;
141 char c;
142START :
143 CK;
144 CODE( 21 );
145 pt = (NODE*)malloc( sizeof( NODE ) ); /**//* 21 */
146 CD( 22 );
147 pt->link = 0; /**//* 22 */
148 CD( 23 );
149 pt->coef = 0; /**//* 23 */
150 CD( 24 );
151 pt->exp = 0; /**//* 24 */
152 ch = pt;
153 CDN( 25 );
154 pc = ch; /**//* 25 */
155 CDS( 26 );
156 pa = ah; /**//* 26 */
157 CDS( 27 );
158 pb = bh; /**//* 27 */
159 CDS( 29 );
160 /**//* 28 */
161 while ( pa && pb ) { /**//* 29 */
162 CD( 30 );
163 if ( pa->exp == pb->exp ) { /**//* 30 */
164 CD( 31 );
165 c = '='; /**//* 31 */
166 }
167 else {
168 CD( 32 );
169 if ( pa->exp > pb->exp ) {/**//* 32 */
170 CD( 33 );
171 c = '>'; /**//* 33 */
172 }
173 else { /**//* 34 */
174 CD( 34 );
175 CD( 35 );
176 c = '<'; /**//* 35 */
177 }
178
179 }
180 CD( 37 );
181 /**//* 36 */
182 if ( c == '=' ) {
183 CD( 38 );
184 }
185 else if ( c == '>' ) {
186 CD( 46 );
187 }
188 else {
189 CD( 52 );
190 }
191 switch ( c ) { /**//* 37 */
192 case '=' : /**//* 38 */
193 CD( 39 );
194 if ( pa->coef + pb->coef ) { /**//* 39 */
195 CD( 40 );
196 CD( 41 );
197 CD( 42 );
198 pc = CalcInsert( pc, /**//* 40 */
199 pa->coef + pb->coef, /**//* 41 */
200 pa->exp ); /**//* 42 */
201 CDN( 43 );
202 }
203 else {
204 CD( 43 );
205 }
206 pa = pa->link; /**//* 43 */
207 CDS( 44 );
208 pb = pb->link; /**//* 44 */
209 CDS( 45 );
210 CD( 29 );
211 break; /**//* 45 */
212 case '>' : /**//* 46 */
213 CD( 47 );
214 CD( 48 );
215 CD( 49 );
216 pc = CalcInsert( pc, /**//* 47 */
217 pa->coef, /**//* 48 */
218 pa->exp ); /**//* 49 */
219 CDN( 50 );
220 pa = pa->link; /**//* 50 */
221 CDS( 51 );
222 CD( 29 );
223 break; /**//* 51 */
224 case '<' : /**//* 52 */
225 CD( 53 );
226 CD( 54 );
227 CD( 55 );
228 pc = CalcInsert( pc, /**//* 53 */
229 pb->coef, /**//* 54 */
230 pb->exp ); /**//* 55 */
231 CDN( 56 );
232 pb = pb->link; /**//* 56 */
233 CDS( 57 );
234 CD( 29 );
235 break; /**//* 57 */
236 }
237 }
238 CD( 61 );
239 /**//* 60 */
240 while ( pa ) { /**//* 61 */
241 CD( 62 );
242 CD( 63 );
243 CD( 64 );
244 pc = CalcInsert( pc, /**//* 62 */
245 pa->coef, /**//* 63 */
246 pa->exp ); /**//* 64 */
247 CDN( 65 );
248 pa = pa->link; /**//* 65 */
249 CDS( 61 );
250 }
251 CD( 68 );
252 /**//* 67 */
253 while ( pb ) { /**//* 68 */
254 CD( 69 );
255 CD( 70 );
256 CD( 71 );
257 pc = CalcInsert( pc, /**//* 69 */
258 pb->coef, /**//* 70 */
259 pb->exp ); /**//* 71 */
260 CDN( 72 );
261 pb = pb->link; /**//* 72 */
262 CDS( 68 );
263 }
264 CD( 75 );
265 /**//* 74 */
266 pc->link = 0; /**//* 75 */
267 CD( 76 );
268 pc = ch; /**//* 76 */
269 CDS( 77 );
270 if ( ch->link ) { /**//* 77 */
271 CD( 78 );
272 CD( 79 );
273 ch = ch->link; /**//* 78 */
274 free( pc ); /**//* 79 */
275 CDE( 81 );
276 }
277 else {
278 CDS( 81 );
279 }
280 /**//* return ch */ /**//* 81 */
281 CDS( 82 );
282 SendMessage( hCtrlWnd, WM_MY_NOTIFY, MY_NOTIFY_CTRL_WND_CALC_OVER, 0 );
283 goto START;
284 return 0;
285}
286
CodeWnd.c
1#include "CodeWnd.h"
2
3
4TCHAR szCodeWndClassName[] = TEXT( "Code Window Class Name" );
5TCHAR szCodeWndName[] = TEXT( "多项式加法代码" );
6
7
8INT iTotLineVisible = 0;
9
10
11LRESULT CALLBACK CodeWndProc( HWND, UINT, WPARAM, LPARAM );
12LRESULT CodeWndOnMyNotify( HWND, WPARAM, LPARAM );
13LRESULT CodeWndOnPaint( HWND, WPARAM, LPARAM );
14LRESULT CodeWndOnCreate( HWND, WPARAM, LPARAM );
15LRESULT CodeWndOnSize( HWND, WPARAM, LPARAM );
16
17
18INT CodeWndInit( VOID ) {
19 WNDCLASSEX wc;
20
21 wc.cbClsExtra = 0;
22 wc.cbSize = sizeof( WNDCLASSEX );
23 wc.cbWndExtra = 0;
24 wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
25 wc.hCursor = LoadCursor( 0, IDC_ARROW );
26 wc.hIcon = LoadIcon( 0, IDI_APPLICATION );
27 wc.hIconSm = 0;
28 wc.hInstance = hInst;
29 wc.lpfnWndProc = CodeWndProc;
30 wc.lpszClassName = szCodeWndClassName;
31 wc.lpszMenuName = 0;
32 wc.style = 0;
33 if ( ! RegisterClassEx( &wc ) ) {
34 MessageBox( 0, TEXT( "Register CodeWndClass Failed" ),
35 TEXT( "Failed" ), MB_ICONWARNING | MB_OK );
36 return 1;
37 }
38
39 hCodeWnd = CreateWindowEx( 0, szCodeWndClassName, szCodeWndName,
40 WS_OVERLAPPEDWINDOW,
41 CODE_WND_POS_X, CODE_WND_POS_Y, CODE_WND_WIDTH, CODE_WND_HEIGHT,
42 hCtrlWnd, 0, hInst, 0 );
43 if ( ! hCodeWnd ) {
44 MessageBox( 0, TEXT( "Create CodeWnd Failed" ),
45 TEXT( "Failed" ), MB_ICONWARNING | MB_OK );
46 return 1;
47 }
48 ShowWindow( hCodeWnd, SW_HIDE );
49 UpdateWindow( hCodeWnd );
50 return 0;
51}
52
53LRESULT CALLBACK CodeWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
54 switch ( uMsg ) {
55 case WM_MY_NOTIFY :
56 return CodeWndOnMyNotify( hWnd, wParam, lParam );
57 case WM_PAINT :
58 return CodeWndOnPaint( hWnd, wParam, lParam );
59 case WM_SIZE :
60 return CodeWndOnSize( hWnd, wParam, lParam );
61 case WM_CREATE :
62 return CodeWndOnCreate( hWnd, wParam, lParam );
63 case WM_CLOSE :
64 PostMessage( hCtrlWnd, WM_MY_NOTIFY, MY_NOTIFY_CTRL_WND_CODE_CLOSE, 0 );
65 return 0;
66 }
67 return DefWindowProc( hWnd, uMsg, wParam, lParam );
68}
69
70LRESULT CodeWndOnMyNotify( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
71 static INT iLine = 0;
72
73 INT iOff, iLen, icnt = 0, iLineFirst;
74 HWND hChild = GetDlgItem( hWnd, CODE_WND_EDIT_ID_CODE_LINE );
75
76 switch ( wParam ) {
77 case MY_NOTIFY_CODE_WND_INIT :
78 iLine = 17;
79 ++icnt;
80 case MY_NOTIFY_CODE_WND_STEP :
81 if ( icnt == 0 ) {
82 iLine = lParam;
83 }
84 iLineFirst = SendMessage( hChild, EM_GETFIRSTVISIBLELINE, 0, 0 );
85 if ( ( iLine < iLineFirst ) || ( iLineFirst + iTotLineVisible <= iLine ) ) {
86 SendMessage( hChild, EM_LINESCROLL, 0, iLine - iLineFirst - iTotLineVisible / 3 );
87 }
88 iOff = SendMessage( hChild, EM_LINEINDEX, iLine, 0 );
89 iLen = SendMessage( hChild, EM_LINELENGTH, iLine, 0 );
90 SendMessage( hChild, EM_SETSEL, iOff, iOff + iLen );
91 InvalidateRect( hWnd, 0, 1 );
92 break;
93 }
94 return 0;
95}
96
97LRESULT CodeWndOnPaint( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
98 return DefWindowProc( hWnd, WM_PAINT, wParam, lParam );
99}
100
101LRESULT CodeWndOnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
102 RECT rt;
103 HWND hc;
104
105 GetClientRect( hWnd, &rt );
106 hc = CreateWindowEx( 0, TEXT( "edit" ), CODE_LINE,
107 WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE | ES_READONLY |
108 ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_LEFT |
109 ES_NOHIDESEL,
110 rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top,
111 hWnd, (HMENU)CODE_WND_EDIT_ID_CODE_LINE, hInst, 0 );
112 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
113 return 0;
114}
115
116LRESULT CodeWndOnSize( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
117 MoveWindow( GetDlgItem( hWnd, CODE_WND_EDIT_ID_CODE_LINE ), 0, 0, LOWORD(lParam), HIWORD(lParam), 1 );
118 iTotLineVisible = ( HIWORD(lParam) - GetSystemMetrics( SM_CYHSCROLL ) ) / ( FONT_HEIGHT + 1 );
119 return 0;
120}
121
CtrlWnd.c
1#include "CtrlWnd.h"
2
3
4TCHAR szCtrlWndClassName[] = TEXT( "Ctrl Window Class Name" );
5TCHAR szCtrlWndName[] = TEXT( "链表实现的多项式加法动态演示" );
6
7
8LRESULT CALLBACK CtrlWndProc( HWND, UINT, WPARAM, LPARAM );
9LRESULT CtrlWndOnCommand( HWND, WPARAM, LPARAM );
10LRESULT CtrlWndOnMyNotify( HWND, WPARAM, LPARAM );
11LRESULT CtrlWndOnTimer( HWND, WPARAM, LPARAM );
12LRESULT CtrlWndOnDestroy( HWND, WPARAM, LPARAM );
13LRESULT CtrlWndOnPaint( HWND, WPARAM, LPARAM );
14LRESULT CtrlWndOnCreate( HWND, WPARAM, LPARAM );
15
16
17INT CtrlWndInit( VOID ) {
18 WNDCLASSEX wc;
19
20 wc.cbClsExtra = 0;
21 wc.cbSize = sizeof( WNDCLASSEX );
22 wc.cbWndExtra = 0;
23 wc.hbrBackground = (HBRUSH)( COLOR_BTNFACE + 1 );
24 wc.hCursor = LoadCursor( 0, IDC_ARROW );
25 wc.hIcon = LoadIcon( 0, IDI_APPLICATION );
26 wc.hIconSm = 0;
27 wc.hInstance = hInst;
28 wc.lpfnWndProc = CtrlWndProc;
29 wc.lpszClassName = szCtrlWndClassName;
30 wc.lpszMenuName = 0;
31 wc.style = 0;
32 if ( ! RegisterClassEx( &wc ) ) {
33 MessageBox( 0, TEXT( "Register CtrlWndClass Failed" ),
34 TEXT( "Failed" ), MB_ICONWARNING | MB_OK );
35 return 1;
36 }
37
38 hCtrlWnd = CreateWindowEx( 0, szCtrlWndClassName, szCtrlWndName,
39 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_BORDER,
40 CTRL_WND_POS_X, CTRL_WND_POS_Y, CTRL_WND_WIDTH, CTRL_WND_HEIGHT,
41 0, 0, hInst, 0 );
42 if ( ! hCtrlWnd ) {
43 MessageBox( 0, TEXT( "Create CtrlWnd Failed" ),
44 TEXT( "Failed" ), MB_ICONWARNING | MB_OK );
45 return 1;
46 }
47 ShowWindow( hCtrlWnd, SW_NORMAL );
48 UpdateWindow( hCtrlWnd );
49 return 0;
50}
51
52LRESULT CALLBACK CtrlWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
53 switch ( uMsg ) {
54 case WM_COMMAND :
55 return CtrlWndOnCommand( hWnd, wParam, lParam );
56 case WM_MY_NOTIFY :
57 return CtrlWndOnMyNotify( hWnd, wParam, lParam );
58 case WM_TIMER :
59 return CtrlWndOnTimer( hWnd, wParam, lParam );
60 case WM_DESTROY :
61 return CtrlWndOnDestroy( hWnd, wParam, lParam );
62 case WM_PAINT :
63 return CtrlWndOnPaint( hWnd, wParam, lParam );
64 case WM_CREATE :
65 return CtrlWndOnCreate( hWnd, wParam, lParam );
66 }
67 return DefWindowProc( hWnd, uMsg, wParam, lParam );
68}
69
70LRESULT CtrlWndOnCommand( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
71 HWND hChild = (HWND)lParam, hTag = 0;
72 INT iCheck;
73
74 switch ( LOWORD(wParam) ) {
75 case CTRL_WND_MENU_ID_EXIT :
76 PostMessage( hWnd, WM_CLOSE, 0, 0 );
77 break;
78 case CTRL_WND_BUTTON_ID_VIEW_CODE :
79 hTag = hCodeWnd;
80 case CTRL_WND_BUTTON_ID_VIEW_DISP :
81 if ( hTag == 0 ) hTag = hDispWnd;
82 iCheck = (INT)SendMessage( hChild, BM_GETCHECK, 0, 0 );
83 if ( iCheck ) {
84 SendMessage( hChild, BM_SETCHECK, 0, 0 );
85 ShowWindow( hTag, SW_HIDE );
86 }
87 else {
88 SendMessage( hChild, BM_SETCHECK, 1, 0 );
89 ShowWindow( hTag, SW_NORMAL );
90 }
91 break;
92 case CTRL_WND_BUTTON_ID_RUN_STEP :
93 fRun = CALC_STATE_RUN_STEP;
94 hTag = GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_RUN_PIPELINE );
95 case CTRL_WND_BUTTON_ID_RUN_PIPELINE :
96 if ( hTag == 0 ) {
97 fRun = CALC_STATE_RUN_PIPELINE;
98 hTag = GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_RUN_STEP );
99 }
100 SendMessage( hChild, BM_SETCHECK, 1, 0 );
101 SendMessage( hTag, BM_SETCHECK, 0, 0 );
102 break;
103 case CTRL_WND_BUTTON_ID_EXP_CLEAR_STOP :
104 if ( fCalc == CALC_STATE_CALC_INIT ) {
105 CalcInit();
106 SetWindowText( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_A ), TEXT( "" ) );
107 SetWindowText( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_B ), TEXT( "" ) );
108 SetWindowText( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_C ), TEXT( "" ) );
109 }
110 else {
111 fCalc = CALC_STATE_CALC_INIT;
112 SetWindowText( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_EXP_CLEAR_STOP ), TEXT( "清空" ) );
113 SetWindowText( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_EXP_START_CONTINUE ), TEXT( "开始执行" ) );
114 EnableWindow( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_EXP_START_CONTINUE ), 1 );
115 EnableWindow( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_A ), 1 );
116 EnableWindow( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_B ), 1 );
117 EnableWindow( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_RUN_STEP ), 1 );
118 EnableWindow( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_RUN_PIPELINE ), 1 );
119 }
120 break;
121 case CTRL_WND_BUTTON_ID_EXP_START_CONTINUE :
122 if ( fCalc == CALC_STATE_CALC_INIT ) {
123 GetWindowText( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_A ), szExpA, MAX_EXP_SZ_LEN );
124 GetWindowText( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_B ), szExpB, MAX_EXP_SZ_LEN );
125 CalcInit();
126 SetWindowText( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_C ), TEXT( "" ) );
127 if ( ( CalcParse( szExpA, &ah ) == 0 ) && ( CalcParse( szExpB, &bh ) == 0 ) ) {
128 fCalc = CALC_STATE_CALC_WAIT;
129 EnableWindow( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_A ), 0 );
130 EnableWindow( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_B ), 0 );
131 EnableWindow( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_RUN_STEP ), 0 );
132 EnableWindow( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_RUN_PIPELINE ), 0 );
133 SetWindowText( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_EXP_CLEAR_STOP ), TEXT( "停止" ) );
134 if ( fRun == CALC_STATE_RUN_STEP ) {
135 SetWindowText( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_EXP_START_CONTINUE ), TEXT( "继续" ) );
136 }
137 else if ( fRun == CALC_STATE_RUN_PIPELINE ) {
138 EnableWindow( GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_EXP_START_CONTINUE ), 0 );
139 }
140 else {
141 MessageBox( hWnd, TEXT( "fRun 值错误!" ), TEXT( "错误!" ), MB_ICONERROR | MB_OK );
142 }
143 }
144 else {
145 MessageBox( hWnd, TEXT( "多项式未知数为 x ,小写,从高次到低次\n表达式中间无空格\na^b 表示 a 的 b 次方\n例如:\n-x^7+3\n3x^2-x\nx+1" ), TEXT( "输入错误!" ), MB_ICONERROR | MB_OK );
146 }
147 }
148 else {
149 fCalc = CALC_STATE_CALC_CALC;
150 }
151 break;
152 }
153 return 0;
154}
155
156LRESULT CtrlWndOnMyNotify( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
157 HWND hChild;
158 switch ( wParam ) {
159 case MY_NOTIFY_CTRL_WND_CODE_CLOSE :
160 hChild = GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_VIEW_CODE );
161 ShowWindow( hCodeWnd, SW_HIDE );
162 SendMessage( hChild, BM_SETCHECK, 0, 0 );
163 break;
164 case MY_NOTIFY_CTRL_WND_DISP_CLOSE :
165 hChild = GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_VIEW_DISP );
166 ShowWindow( hDispWnd, SW_HIDE );
167 SendMessage( hChild, BM_SETCHECK, 0, 0 );
168 break;
169 case MY_NOTIFY_CTRL_WND_CALCED :
170 if ( fCalc == CALC_STATE_CALC_INIT )
171 break;
172 if ( fRun == CALC_STATE_RUN_PIPELINE )
173 fCalc = CALC_STATE_CALC_WAIT;
174 else if ( fRun == CALC_STATE_RUN_STEP )
175 fCalc = CALC_STATE_CALC_SLEEP;
176 else {
177 MessageBox( hWnd, TEXT( "fRun 值错误!" ), TEXT( "错误!" ), MB_ICONERROR | MB_OK );
178 break;
179 }
180 if ( CalcToStr( ch, szExpC, MAX_EXP_SZ_LEN ) == 0 )
181 SetWindowText( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_C ), szExpC );
182 else
183 SetWindowText( GetDlgItem( hWnd, CTRL_WND_EDIT_ID_C ), TEXT( "" ) );
184 break;
185 case MY_NOTIFY_CTRL_WND_CALC_OVER :
186 SendMessage( hCtrlWnd, WM_COMMAND, CTRL_WND_BUTTON_ID_EXP_CLEAR_STOP, 0 );
187 break;
188 }
189 return 0;
190}
191
192LRESULT CtrlWndOnTimer( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
193 static INT icnt = 0;
194 if ( fCalc == CALC_STATE_CALC_WAIT ) {
195 if ( ++icnt >= CTRL_WND_DELTA_TIME_PIECE ) {
196 fCalc = CALC_STATE_CALC_CALC;
197 icnt = 0;
198 }
199 }
200 else {
201 icnt = 0;
202 }
203 return 0;
204}
205
206LRESULT CtrlWndOnDestroy( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
207 KillTimer( hWnd, CTRL_WND_TIMER_ID_DELTA );
208 PostQuitMessage( 0 );
209 return 0;
210}
211
212LRESULT CtrlWndOnPaint( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
213 return DefWindowProc( hWnd, WM_PAINT, wParam, lParam );
214}
215
216LRESULT CtrlWndOnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
217 HMENU hMenu, hMenuPopup;
218 HWND hc;
219
220 /**//* MENU */
221 hMenu = CreateMenu();
222 hMenuPopup = CreateMenu();
223 AppendMenu( hMenuPopup, MF_STRING, CTRL_WND_MENU_ID_EXIT, TEXT( "退出" ) );
224 AppendMenu( hMenu, MF_POPUP, (UINT_PTR)hMenuPopup, TEXT( "程序" ) );
225 SetMenu( hWnd, hMenu );
226
227 /**//* EXP */
228 CreateWindowEx( 0, TEXT( "button" ), TEXT( "" ),
229 WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
230 CTRL_WND_EXP_POS_X, CTRL_WND_EXP_POS_Y, CTRL_WND_EXP_WIDTH, CTRL_WND_EXP_HEIGHT,
231 hWnd, (HMENU)CTRL_WND_BUTTON_ID_EXP, hInst, 0 );
232 /**//* A */
233 hc = CreateWindowEx( 0, TEXT( "edit" ), TEXT( "A=" ),
234 WS_CHILD | WS_VISIBLE | ES_RIGHT | ES_READONLY,
235 CTRL_WND_EXP_NOTE_A_POS_X, CTRL_WND_EXP_NOTE_A_POS_Y, CTRL_WND_EXP_NOTE_A_WIDTH, CTRL_WND_EXP_NOTE_A_HEIGHT,
236 hWnd, (HMENU)CTRL_WND_NOTE_ID_A, hInst, 0 );
237 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
238 hc = CreateWindowEx( 0, TEXT( "edit" ), TEXT( "" ),
239 WS_CHILD | WS_VISIBLE | ES_RIGHT | WS_BORDER | ES_AUTOHSCROLL,
240 CTRL_WND_EXP_EDIT_A_POS_X, CTRL_WND_EXP_EDIT_A_POS_Y, CTRL_WND_EXP_EDIT_A_WIDTH, CTRL_WND_EXP_EDIT_A_HEIGHT,
241 hWnd, (HMENU)CTRL_WND_EDIT_ID_A, hInst, 0 );
242 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
243
244 /**//* B */
245 hc = CreateWindowEx( 0, TEXT( "edit" ), TEXT( "B=" ),
246 WS_CHILD | WS_VISIBLE | ES_RIGHT | ES_READONLY,
247 CTRL_WND_EXP_NOTE_B_POS_X, CTRL_WND_EXP_NOTE_B_POS_Y, CTRL_WND_EXP_NOTE_B_WIDTH, CTRL_WND_EXP_NOTE_B_HEIGHT,
248 hWnd, (HMENU)CTRL_WND_NOTE_ID_B, hInst, 0 );
249 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
250 hc = CreateWindowEx( 0, TEXT( "edit" ), TEXT( "" ),
251 WS_CHILD | WS_VISIBLE | ES_RIGHT | WS_BORDER | ES_AUTOHSCROLL,
252 CTRL_WND_EXP_EDIT_B_POS_X, CTRL_WND_EXP_EDIT_B_POS_Y, CTRL_WND_EXP_EDIT_B_WIDTH, CTRL_WND_EXP_EDIT_B_HEIGHT,
253 hWnd, (HMENU)CTRL_WND_EDIT_ID_B, hInst, 0 );
254 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
255
256 /**//* C */
257 hc = CreateWindowEx( 0, TEXT( "edit" ), TEXT( "C=" ),
258 WS_CHILD | WS_VISIBLE | ES_RIGHT | ES_READONLY,
259 CTRL_WND_EXP_NOTE_C_POS_X, CTRL_WND_EXP_NOTE_C_POS_Y, CTRL_WND_EXP_NOTE_C_WIDTH, CTRL_WND_EXP_NOTE_C_HEIGHT,
260 hWnd, (HMENU)CTRL_WND_NOTE_ID_C, hInst, 0 );
261 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
262 hc = CreateWindowEx( 0, TEXT( "edit" ), TEXT( "" ),
263 WS_CHILD | WS_VISIBLE | ES_RIGHT | WS_BORDER | ES_READONLY | ES_AUTOHSCROLL,
264 CTRL_WND_EXP_EDIT_C_POS_X, CTRL_WND_EXP_EDIT_C_POS_Y, CTRL_WND_EXP_EDIT_C_WIDTH, CTRL_WND_EXP_EDIT_C_HEIGHT,
265 hWnd, (HMENU)CTRL_WND_EDIT_ID_C, hInst, 0 );
266 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
267
268 /**//* CLEAR_STOP */
269 hc = CreateWindowEx( 0, TEXT( "button" ), TEXT( "清空" ),
270 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
271 CTRL_WND_EXP_CLEAR_STOP_POS_X, CTRL_WND_EXP_CLEAR_STOP_POS_Y, CTRL_WND_EXP_CLEAR_STOP_WIDTH, CTRL_WND_EXP_CLEAR_STOP_HEIGHT,
272 hWnd, (HMENU)CTRL_WND_BUTTON_ID_EXP_CLEAR_STOP, hInst, 0 );
273 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
274
275 /**//* START_CONTINUE */
276 hc = CreateWindowEx( 0, TEXT( "button" ), TEXT( "开始执行" ),
277 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
278 CTRL_WND_EXP_START_CONTINUE_POS_X, CTRL_WND_EXP_START_CONTINUE_POS_Y, CTRL_WND_EXP_START_CONTINUE_WIDTH, CTRL_WND_EXP_START_CONTINUE_HEIGHT,
279 hWnd, (HMENU)CTRL_WND_BUTTON_ID_EXP_START_CONTINUE, hInst, 0 );
280 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
281
282 /**//* VIEW */
283 CreateWindowEx( 0, TEXT( "button" ), TEXT( "" ),
284 WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
285 CTRL_WND_VIEW_POS_X, CTRL_WND_VIEW_POS_Y, CTRL_WND_VIEW_WIDTH, CTRL_WND_VIEW_HEIGHT,
286 hWnd, (HMENU)CTRL_WND_BUTTON_ID_VIEW, hInst, 0 );
287
288 /**//* CODE */
289 hc = CreateWindowEx( 0, TEXT( "button" ), TEXT( "代码窗口" ),
290 WS_CHILD | WS_VISIBLE | BS_CHECKBOX,
291 CTRL_WND_VIEW_CODE_POS_X, CTRL_WND_VIEW_CODE_POS_Y, CTRL_WND_VIEW_CODE_WIDTH, CTRL_WND_VIEW_CODE_HEIGHT,
292 hWnd, (HMENU)CTRL_WND_BUTTON_ID_VIEW_CODE, hInst, 0 );
293 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
294
295 /**//* DISP */
296 hc = CreateWindowEx( 0, TEXT( "button" ), TEXT( "演示窗口" ),
297 WS_CHILD | WS_VISIBLE | BS_CHECKBOX,
298 CTRL_WND_VIEW_DISP_POS_X, CTRL_WND_VIEW_DISP_POS_Y, CTRL_WND_VIEW_DISP_WIDTH, CTRL_WND_VIEW_DISP_HEIGHT,
299 hWnd, (HMENU)CTRL_WND_BUTTON_ID_VIEW_DISP, hInst, 0 );
300 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
301
302 /**//* RUN */
303 CreateWindowEx( 0, TEXT( "button" ), TEXT( "" ),
304 WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
305 CTRL_WND_RUN_POS_X, CTRL_WND_RUN_POS_Y, CTRL_WND_RUN_WIDTH, CTRL_WND_RUN_HEIGHT,
306 hWnd, (HMENU)CTRL_WND_BUTTON_ID_RUN, hInst, 0 );
307
308 /**//* STEP */
309 hc = CreateWindowEx( 0, TEXT( "button" ), TEXT( "单步执行" ),
310 WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
311 CTRL_WND_RUN_STEP_POS_X, CTRL_WND_RUN_STEP_POS_Y, CTRL_WND_RUN_STEP_WIDTH, CTRL_WND_RUN_STEP_HEIGHT,
312 hWnd, (HMENU)CTRL_WND_BUTTON_ID_RUN_STEP, hInst, 0 );
313 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
314
315 /**//* PIPELINE */
316 hc = CreateWindowEx( 0, TEXT( "button" ), TEXT( "流水执行" ),
317 WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
318 CTRL_WND_RUN_PIPELINE_POS_X, CTRL_WND_RUN_PIPELINE_POS_Y, CTRL_WND_RUN_PIPELINE_WIDTH, CTRL_WND_RUN_PIPELINE_HEIGHT,
319 hWnd, (HMENU)CTRL_WND_BUTTON_ID_RUN_PIPELINE, hInst, 0 );
320 SendMessage( hc, WM_SETFONT, (WPARAM)hFont, 0 );
321
322 /**//* TIMER */
323 SetTimer( hWnd, CTRL_WND_TIMER_ID_DELTA, CTRL_WND_DELTA_TIME / CTRL_WND_DELTA_TIME_PIECE, 0 );
324
325 /**//* CALC STATE */
326 PostMessage( hWnd, WM_COMMAND, MAKEWPARAM( CTRL_WND_BUTTON_ID_RUN_PIPELINE, 0 ), (LPARAM)GetDlgItem( hWnd, CTRL_WND_BUTTON_ID_RUN_PIPELINE ) );
327 return 0;
328}
329
DispWnd.c
1#include "DispWnd.h"
2
3
4TCHAR szDispWndClassName[] = TEXT( "Disp Window Class Name" );
5TCHAR szDispWndName[] = TEXT( "多项式加法图形演示" );
6HPEN hPen;
7
8
9LRESULT CALLBACK DispWndProc( HWND, UINT, WPARAM, LPARAM );
10LRESULT DispWndOnCreate( HWND, WPARAM, LPARAM );
11LRESULT DispWndOnPaint( HWND, WPARAM, LPARAM );
12LRESULT DispWndOnMyNotify( HWND, WPARAM, LPARAM );
13LRESULT DispWndOnDestroy( HWND, WPARAM, LPARAM );
14
15LRESULT DispWndOnStep( HWND, LPARAM );
16
17VOID DispWndDrawList( HDC, LPARAM, INT, INT, NODE *, PCTSTR, INT, NODE *, PCTSTR, INT );
18
19INT DispWndInit( VOID ) {
20 WNDCLASSEX wc;
21
22 wc.cbClsExtra = 0;
23 wc.cbSize = sizeof( WNDCLASSEX );
24 wc.cbWndExtra = 0;
25 wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
26 wc.hCursor = LoadCursor( 0, IDC_ARROW );
27 wc.hIcon = LoadIcon( 0, IDI_APPLICATION );
28 wc.hIconSm = 0;
29 wc.hInstance = hInst;
30 wc.lpfnWndProc = DispWndProc;
31 wc.lpszClassName = szDispWndClassName;
32 wc.lpszMenuName = 0;
33 wc.style = 0;
34 if ( ! RegisterClassEx( &wc ) ) {
35 MessageBox( 0, TEXT( "Register DispWndClass Failed" ),
36 TEXT( "Failed" ), MB_ICONWARNING | MB_OK );
37 return 1;
38 }
39
40 hDispWnd = CreateWindowEx( 0, szDispWndClassName, szDispWndName,
41 WS_OVERLAPPEDWINDOW,
42 DISP_WND_POS_X, DISP_WND_POS_Y, DISP_WND_WIDTH, DISP_WND_HEIGHT,
43 hCtrlWnd, 0, hInst, 0 );
44 if ( ! hDispWnd ) {
45 MessageBox( 0, TEXT( "Create DispWnd Failed" ),
46 TEXT( "Failed" ), MB_ICONWARNING | MB_OK );
47 return 1;
48 }
49 ShowWindow( hDispWnd, SW_HIDE );
50 UpdateWindow( hDispWnd );
51 return 0;
52}
53
54LRESULT CALLBACK DispWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
55 switch ( uMsg ) {
56 case WM_PAINT :
57 return DispWndOnPaint( hWnd, wParam, lParam );
58 case WM_CLOSE :
59 PostMessage( hCtrlWnd, WM_MY_NOTIFY, MY_NOTIFY_CTRL_WND_DISP_CLOSE, 0 );
60 return 0;
61 case WM_MY_NOTIFY :
62 return DispWndOnMyNotify( hWnd, wParam, lParam );
63 case WM_CREATE :
64 return DispWndOnCreate( hWnd, wParam, lParam );
65 case WM_DESTROY :
66 return DispWndOnDestroy( hWnd, wParam, lParam );
67 }
68 return DefWindowProc( hWnd, uMsg, wParam, lParam );
69}
70
71LRESULT DispWndOnMyNotify( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
72 switch ( wParam ) {
73 case MY_NOTIFY_DISP_WND_INIT :
74 InvalidateRect( hWnd, 0, 1 );
75 break;
76 case MY_NOTIFY_DISP_WND_STEP :
77 InvalidateRect( hWnd, 0, 1 );
78 return DispWndOnStep( hWnd, lParam );
79 }
80 return 0;
81}
82
83LRESULT DispWndOnCreate( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
84 hPen = CreatePen( PS_SOLID, NODE_PEN_WIDTH, NODE_PEN_COLOR );
85 return 0;
86}
87
88LRESULT DispWndOnPaint( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
89 PAINTSTRUCT ps;
90 HDC hdc;
91 hdc = BeginPaint( hWnd, &ps );
92 EndPaint( hWnd, &ps );
93 return DispWndOnStep( hWnd, MY_NOTIFY_LPARAM_PRED );
94}
95
96LRESULT DispWndOnDestroy( HWND hWnd, WPARAM wParam, LPARAM lParam ) {
97 DeleteObject( hPen );
98 return 0;
99}
100
101LRESULT DispWndOnStep( HWND hWnd, LPARAM lParam ) {
102 static LPARAM lParamPred = 0;
103
104 HDC hdc = GetDC( hWnd );
105
106 if ( lParam == MY_NOTIFY_LPARAM_PRED ) {
107 lParam = lParamPred;
108 }
109
110 SelectObject( hdc, hPen );
111 SelectObject( hdc, hFont );
112
113 DispWndDrawList( hdc, 0, NODE_ORG_POS_X, NODE_ORG_POS_Y + NODE_HEIGHT_UNIT * 0, ah, TEXT( "ah" ), 2, pa, TEXT( "pa" ), 2 );
114 DispWndDrawList( hdc, 0, NODE_ORG_POS_X, NODE_ORG_POS_Y + NODE_HEIGHT_UNIT * 1, bh, TEXT( "bh" ), 2, pb, TEXT( "pb" ), 2 );
115 DispWndDrawList( hdc, lParam, NODE_ORG_POS_X, NODE_ORG_POS_Y + NODE_HEIGHT_UNIT * 2, ch, TEXT( "ch" ), 2, pc, TEXT( "pc" ), 2 );
116
117 ReleaseDC( hWnd, hdc );
118
119 lParamPred = lParam;
120 return 0;
121}
122
123VOID DispWndDrawList( HDC hdc, LPARAM lParam, INT x, INT y, NODE * pList, PCTSTR szHeader, INT iHeaderLen, NODE * pPointer, PCTSTR szPointer, INT iPointerLen ) {
124 NODE *p = pList;
125 TCHAR buf[ 500 ];
126 INT iLen;
127
128 if ( pList ) {
129 TextOut( hdc, x, y + 3, szHeader, iHeaderLen );
130 x += NODE_WIDTH_HEADER;
131 MoveToEx( hdc, x, y + NODE_HEIGHT / 2, 0 );
132 x += NODE_WIDTH_DIST;
133 LineTo( hdc, x, y + NODE_HEIGHT / 2 );
134 if ( lParam == MY_NOTIFY_LPARAM_BLANK_FIRST ) {
135 MoveToEx( hdc, x, y + NODE_HEIGHT / 2, 0 );
136 x += NODE_WIDTH_UNIT;
137 LineTo( hdc, x, y + NODE_HEIGHT / 2 );
138 }
139 }
140 while ( p ) {
141 if ( ( p->link == 0 ) && ( lParam == MY_NOTIFY_LPARAM_OUT_LAST ) ) {
142 MoveToEx( hdc, x, y + NODE_HEIGHT / 2, 0 );
143 x += NODE_WIDTH_UNIT;
144 LineTo( hdc, x, y + NODE_HEIGHT / 2 );
145 }
146
147 Rectangle( hdc, x, y, x + NODE_WIDTH, y + NODE_HEIGHT );
148 Rectangle( hdc, x + NODE_WIDTH_COEF, y, x + NODE_WIDTH_COEF + NODE_WIDTH_EXP, y + NODE_HEIGHT );
149 MoveToEx( hdc, x + NODE_WIDTH - NODE_WIDTH_LINK / 2, y + NODE_HEIGHT / 2, 0 );
150 LineTo( hdc, x + NODE_WIDTH_UNIT, y + NODE_HEIGHT / 2 );
151
152 iLen = wsprintf( buf, TEXT( "%d" ), p->coef );
153 TextOut( hdc, x + 3, y + 3, buf, iLen );
154 iLen = wsprintf( buf, TEXT( "%d" ), p->exp );
155 TextOut( hdc, x + 3 + NODE_WIDTH_COEF, y + 3, buf, iLen );
156
157 if ( p == pPointer ) {
158 TextOut( hdc, x + 3, y + NODE_HEIGHT + NODE_POINTER_HEIGHT_DIST, szPointer, iPointerLen );
159 MoveToEx( hdc, x + NODE_WIDTH_COEF / 2, y + NODE_HEIGHT + NODE_POINTER_HEIGHT_DIST, 0 );
160 LineTo( hdc, x + NODE_WIDTH_COEF / 2, y + NODE_HEIGHT );
161 }
162
163 p = p->link;
164 x += NODE_WIDTH_UNIT;
165 }
166 if ( pList ) {
167 MoveToEx( hdc, x, y + NODE_HEIGHT / 2, 0 );
168 LineTo( hdc, x, y + NODE_HEIGHT );
169 if ( pPointer == 0 ) {
170 TextOut( hdc, x + 3, y + NODE_HEIGHT + NODE_POINTER_HEIGHT_DIST, szPointer, iPointerLen );
171 MoveToEx( hdc, x + NODE_WIDTH_COEF / 2, y + NODE_HEIGHT + NODE_POINTER_HEIGHT_DIST, 0 );
172 LineTo( hdc, x + NODE_WIDTH_COEF / 2, y + NODE_HEIGHT );
173 }
174 }
175}
176
Poly.c
1#include "Poly.h"
2#include <process.h>
3
4
5HINSTANCE hInst;
6HWND hCtrlWnd, hDispWnd, hCodeWnd;
7INT fRun, fCalc;
8NODE *ah, *bh, *ch, *pa, *pb, *pc;
9TCHAR szExpA[ MAX_EXP_SZ_LEN ], szExpB[ MAX_EXP_SZ_LEN ], szExpC[ MAX_EXP_SZ_LEN ];
10
11/**//* 需要释放的资源 */
12HFONT hFont;
13
14
15VOID PolyInit( VOID ) {
16 LOGFONT lf;
17
18 fRun = CALC_STATE_RUN_INIT;
19 fCalc = CALC_STATE_CALC_INIT;
20 ah = bh = ch = 0;
21 pa = pb = pc = (NODE*)(1);
22
23 GetObject( GetStockObject( DEFAULT_GUI_FONT ), sizeof(lf), &lf );
24 lf.lfHeight = FONT_HEIGHT;
25 lf.lfWeight = FONT_WEIGHT;
26 hFont = CreateFontIndirect( &lf );
27
28 CtrlWndInit();
29 DispWndInit();
30 CodeWndInit();
31 _beginthreadex( 0, 0, Calc, 0, 0, 0 );
32}
33
34VOID PolyFinish( VOID ) {
35 DeleteObject( hFont );
36}
37
38INT APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT iCmdShow ) {
39 MSG msg;
40
41 hInst = hInstance;
42
43 PolyInit();
44
45 while ( GetMessage( &msg, 0, 0, 0 ) ) {
46 TranslateMessage( &msg );
47 DispatchMessage( &msg );
48 }
49
50 PolyFinish();
51
52 return msg.wParam;
53}
54