struct - みる会図書館


検索対象: 月刊 C MAGAZINE 1992年11月号
11件見つかりました。

1. 月刊 C MAGAZINE 1992年11月号

特集 ープログラ テキストの描画 ミンク、 LiSt 4 : 3 : 2 : hello. exe 用定義ファイル He110. def He110 5 : NAME 6 : DESCRIPTION ' 日 el 10 (c) BohYoh Shibata, 1992 ' 10 : DATA Fig. Fig struct tagRECT 7 : EXETYPE 8 : STUB 9 : CODE 11 : HEAPSIZE 12 : STACKSIZE 13 : EXPORTS WINDOWS 3.0 ' WINSTUB. EXE' PRELOAD MOVABLE DI SCARDAB LE PRELOAD MOVABLE MU LTI PLE 1024 8192 WndProc 12 PAINTSTRUCT 型の定義 typedef struct tagPAlNTSTRUCT HDC BOOL RECT BOOL BOOL BYT E hdc ; fErase ; rcPaint; fRestore ; fIncUpdate; rgbReservedC16] ; / / 描画用ディスプレイコンテクスト / / 背景が再描画されたか ? / / 描画すべき矩形領域 / / 予約 ( Wind 。 ws 内部処理用 ) / / 予約 ( Wind 。 ws 内部処理用 ) / / 予約 ( Wind 。 ws 内部処理用 ) } PAINTSTRUCT ; . 13 Table 19 RECT 型の定義 typedef } RECT; int int int int left; top; right; bottom; / / 左端座標 / / 上端座標 / / 右端座標 / / 下端座標 BeginPaint と EndPaint の概要 BeginPaint 形式 解説 戻り値 HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lppaint) : hWnd によって表されるウインドウの描画準備を行い , lpPaint の指す PAINTSTRUCT 構造体デ ータに , 描画に関する情報を格納する。 指定したウインドウのテパイスコンテクストの識別子 関連項目 EndPaint EndPaint 形式 解説 戻り値 void BeginPaint(HWND hWnd, LPPAINTSTRUCT lppaint) : hWnd によって表されるウインドウの描画の終了処理を行う。 lpPaint は , BeginPainth\ 与えた PA 爪 TSTRUCT 構造体へのポインタてなければならず , 必す BeginPaint と対にして呼び出さな なし けれはならない。 関連項目 BeginPaint それて、は , ウインドウブロシージャが W M PAINT に応答して行っていることを , 具体的に見ていこう。 まず , BeginPaint と EndPaint が対になっ ていることがわかる ( これらの関数の概要を TabIe 19 に示す ) 。 BeginPaint (hwnd, &ps) ・ hdc EndPaint (hwnd, &ps) ・ 第 1 引数は , 描画の対象となるウインドウ のウインドウハンドルて、ある。第 2 引数は , PAINTSTRUCT 構造体へのポインタ (LPP AINTSTRUCT 型として定義されている ) て、 ある。 PAINTSTRUCT 構造体は , Fig. 12 のよ うに定義されている。 ウインドウのクライアント領域に , グラ フィックやテキストを出力するには , デバ イスコンテクストのハンドルが必要て、ある。 BeginPaint は , デバイスコンテクストのハ ンドルを返す。 EndPaint は , BeginPaint が返したハンド ルを解放する役目を持つのて、 , BeginPaint と EndPaint は , 必ず対に呼び出さなければ ならないことに注意しなければならない さて , BeginPaint によって描画の準備を した後は , GetClientRect(hwnd, &rect) ・ によって , クライアント領域を取得する。 GetClientRect の概要を Table 20 に , RECT 構造体の定義を Fig. 13 に示す。 GetClient Rect は , 左上隅を示す left , top には必ず 0 を , right および bottom には , クライアント 領域の幅と高さを格納する。 テキストの出力を行うのが , 次の行て、あ DrawText (hdc, "HeIIO, World!" ー 1 , &rect, DT SINGLE 凵 NE DT CENTER ー DT VCENTER) ; 特集 MS-Windows プログラミング基礎学 63 DrawText の概要については , Table 21

2. 月刊 C MAGAZINE 1992年11月号

ログラマのための List 2 List 2 58 : 59 : 60 : 61 : 64 : 66 : 68 : 69 : 73 : } SDPB; 74 : 75 : typedef struct { / * 内部変数領域 / * DOS ファンクション 52h の ES:BX が指し示す領域の内容 77 : / * mcbtop; 先頭の MCB のセク・メント・アト・レス / * 00h void far *ßdpb; DPB の先頭へのインタ 78 : / * 04h 内部 FCB フ・ロックの先頭へのホ。インタ * / void far *pfcbhead; / * 08h CLOCK テ・ハ・イスを指すホ。インタ void far *ßx)lkdev; / * 0Ch CON テ・ハ・イスを指すホ。インタ 81 : vo id far qmndev : 接続ト・ライフ・中で最大のハ・イト / セクタ * / 82 : uns ignedmax secbyt : / * 10h void far ; / * 12h 内部テ・イスク・ハ・刃アの先頭アト・レス 83 : 内部ト・ライフ・情報の先頭アト・レス void far *Xirvinf; / * 16h 84 : / * 1Ah void far *prsvl; 不明 85 : / * 1Eh 86 : uns igned rsv2 : FCBS=x, y の y 接続ト・ライフ・数 Char drivenum; / * 20h unsigned / * 21h LASTDRIVE ト・ライフ・数 88 : unsigned char lastdrive; LASTDRIVE=Z ならば 1Ah 89 : 90 : } SDOSVAR ; 91 : 92 : void prdrive( SDPB far * ) , search ( char * , char * , int ) , prfile( struct find_t * ) , usage( void ) : 93 : 94 : SDOSVAR far *getdosvar( void ) : 95 : 96 : int main( int argc, char *argv[] ) 97 : { / * 内部変数領域のアト・レス 98 : SDOSVAR far *Xiosvar ; A_HIDDEN ー _A_SYSTEM / * 検索属性 99 : int attr A_SUBDIR; 100 : = getdosvar() ; / * 内部変数領域のアト・レス 101 : harderrl int24h ) ; int 24h ハント・ラの設定 102 : if ( argc ← 1 ) { 103 : prdrive( ) ; / * ト・ライフ・構成の表示 104 : return( 0 ) : 105 : 106 : : 2 & & argv[ 1 ] [ 0 ] : if ( argc ー 107 : usage(); / * 使用法表示 108 : return( 1 ) : 109 : 110 : while ( --argc ) ( 111 : static char rootdir[] ー” ? : 料 112 : char schdirC PATHLEN ] ; / * 検索テ・イレクトリ 113 : / * DPB 114 : SDPB far *ßipb; 115 : for ( + + argv, xipb : ; / * 最初の DPB 116 : FP_OFF( xipb ) ! : 0xffff; / * DPB のチェーンをたどる * / 117 : xipb : -osmajor 〉 = 4 ? 図 p ト > u. dos4. pnextdpb 118 : : EOb->u. dos3. pnextdpb ) { 119 : rootdirC 0 ] ニ ( char ) ( gdpb->drive + ' A' ) : 120 : strcpy( schdir, rmtdir ) : 121 : search( schdir, *argv, attr ) : / * テ・イレクトリ検索 122 : 123 : 124 : return ( 0 ) ; 125 : 126 : 127 : 128 : void prdrive( SDPB far *xipb ) / * ト・ライフ・構成の表示 129 : { ュニットセクタ長クラスタ長 DIR 数クラスタ数テ・イスク容量 \ n ” ) ; printf( 130 : printf( " 131 : do { DPB のチェーンをたどる 132 : printf( ” Xc: Xu u % 6u % 7u % 7u % 101u \ n ” , 133 : xipb->drive + ' A' , IOb->unit, 134 : xlpb->sec-byte, ( xlpb->clsizel + 1 ) * xipb->sec-byte, 135 : 136 : gipb->dirnum, 図 b->data_size ー 1 , ( unsigned 10 ダ ( pdpb->data-size ー 1 ) , 137 : ( EOb->cIsize1 + 1 ) * ) : 138 : xipb : -osmajor 〉ニ 4 ? 図 p ト > u. dos4. pnextdpb : EdPb->U. dos3. pnextdpb; 139 : ) while ( FP-OFF( Edpb ) ! = 0xffff ) : / * 最後の DPB チェック ? 140 : 141 142 : 143 : / * ディレ外リ検索 144 : 145 : * / 00g t00 0h00 ー hf 、 10 凸 int attr ) ョ 148 : 149 : { 150 : struct find t sdta; char PATHLEN ] : 151 : / * 検索テ・イレクトリセット strcpy( schEhth, schdir ) : 154 : strcat( schfile ) : / * 検索ファイルセ外 155 : if ( dos findfirst( &sdta ) - attr, 156 : printf( ” YnXsYn ” , schdir ) ; / * 検索テ・イレ外リ do { 158 : 159 : 160 : 161 : 162 : 163 : 164 : 165 : 166 : 167 : 168 : 169 : 170 : 171 : 172 : 173 : 174 : 175 : 176 : void prfile( struct find_t ) 177 ・ union udate { 178 : struct { 179 : 180 : wr_time; 181 : wr date; ) sdatel; 182 : struct { 183 : 184 : uns s 2 : 5 ; ヨ 185 : 186 : hour : 5 ; 187 : uns igned day : 5 ; 188 : uns month : 4 ; 189 : year : 7 ; } sdate2; 190 : ) udate; 191 : 192 : udate. sdatel. wr-time = rnta->wr-time; / * 最終更新時刻 193 : udate. s 面 tel. ” date = 図ねー > 響 r date ・ / * 最終更新日付 194 : printf( " % -14S 記 % c 記 % 101u [ lx % 6u ー % 02 に % 02u u : % 02u : % 02u \ n " , 195 : 196 : 〉 name, A_SUBDIR ) ? 'd' ( ßdta->attr i b & 197 : 198 : ( 〉 attrib & -A-ARCH ) ? ' 199 : 200 : A_SYSTEM ? ' EHta->attr ib & 201 : A HIDDEN ? 'h' gdta->attrib & -AZRDONLY ) ? ' 202 : r W 203 : Äita->s i ze, / * ファイルサイス・ 204 : xita->s i ze, / * ファイルサイス・ 205 : udate. sdate2. year + 1980 , / * 年 206 : udate. sdate2. month, / * 月 207 : udate. sdate2. day, / * 日 208 : / * 時 udate. sdate2. hour, 209 : udate. sdate2. mrn, / * 分 udate. sdate2. sec2 * 2 ) : 210 : つ 211. 212 : 213 : void usage( void ) / * 使用法表示 214 : static char *msgCJ = { 215 : " \ 033 [ 36m ファイル検索ューティリティ ハ・一シ・ヨン 0.01 \ n " , 216 : "Copyr ight (C) 1991 N. Nakashi \ 033 [m#n#n ” , 217 : ”使用法 1 : search*n}n", 218 : 219 : ト・ライフ・構成を表示します。 }n*n ” , " 使用法 2 : search くファイル 1 > [... くファイ加 > ] \ n \ n " , 220 : 221 : すべての接続ト・ライフ・を検索します。 #n*n ” , ”使用法 3 : search -h#n*n ” , 222 : 223 : ヘルフ。・メッセーシ・を表示します。 *n*n ” , 224 : 225 : 226 : register char **pmsg - msg; 227 : while ( **pmsg ) 228 : printf( *pmsg + 十 ) : 229 : 230. 231 : defined( TURBW_ ) 232 : #if int int24h( void / * int 24h ハント・ラ 233 : 234 : #elif LSI_C ) int far int24h( void ) / * int 24h ハント・ラ 235 : 236 : #e lse 237 : void far int24h( void ) / * int 24h ハント・ラ 238 : #endif 239 : { hardresume( HARDERR_FAIL ) ; / * フ。ロク・ラム上のシステム・コールの失敗 * / 240 : defined( ー R 眦 ) Ⅱ defined( LSI_C ) 241 : #if return ( HARDERR FAI LJ; / * 不要 : コンハ。イル warning 対策 242 : 243 : #endif 244 : 245 : 246 : / * 247 : 返り値内部変数領域のアト・レス 248 : ネ / 249 : SDOSVAR far *getdosvar( void ) 250 : { struct SREGS segs ; 252 : union REGS iregs; 253 : iregs. h. 曲 = 0X52 ; intdosx( &iregs, &iregs, &segs ) : 255 : return( FP( segs. es, iregs. x. bx ) ) : 256 : 257 : } struct dpbstruct far *pnextdpb; / * 次の DPB を指すホ。インタ / * 最後に変更したクラスタ番号 unsigned int last_cl; / * 空きクラスタ数 unsigned int free cl; } dos3; struct { / * セクタ数 / FAT int fat size; int dir—place;/* トト・テ・イレ外リ領域開始論理セクタ番号 far *ßdevhead; / * テ・ハ・イス・ト・ライハ・のホ。インタ void / * メテ・イアテ・イス刎フ。タハ・仆 uns i char ia ; unsigned char diskchange; / * テ・イスク交換を示すフラク・ ・ / * 次の DPB を指すホ。インタ struct dpbstruct far *pnextdpb, / * 最後に変更したクラスタ番号 unsigndi int last cl; / * 空きクラスタ数 unsignai int free cl; } dos4; prfile( &sdta ) : } while ( _dos-findnext( &sdta ) = / * ファイル情報の表示 / * 次ファイル検索 strcpy( schvnth, schdir ) ; / * 検索テ・イレ外リセット strcat( schlhth, ” *. ネ” ) : if ( dos_findfirst( schERth, _A_SUBDIR, &sdta ) dö { if ( sdta. attrib & _A_SUBDIR ) { / * テ・イレクトリ指定チェック if ( sdta. name[ 0 ] = . テ・イレクトリスキ刃。 continue; spr intf ( schlhth, ” % s % s 料” , schdir, sdta. name ) : search ( schgnth, schf i le, attr ) : / * ディレ外リ検索 } while ( -dos-findnext( &sdta ) = / * 次ファイル検索 / * ファ秘情報の表示 / * 最終更新時刻 / * 最終更新日付 / * 秒 / 2 / * 分 0 ~ / * 時 0 ~ / * 日 1 ~ / * 月 1 ~ っ 0 1 人り 0 -0 0 もっ 0 1 人 : 1980 ~ 10 進 ) 16 進 ) / * 検索ディレクトリ / * 検索ファイル / * 検索属性 / * 内部変数領城のアト・レスの取得 96 C MAGAZINE 1992 11

3. 月刊 C MAGAZINE 1992年11月号

新 MS ー DOS プログラミンク入門 プログマのための [ 23 ] 「 Turbo C 十十 1.0 INTRODUCTI [ 26 ] fTurbo C 十十 1.0 LIBRARY RE Run-Time Library Reference 1 , 2 』 , Microsoft ON 』 , BORLAND FERENCE V01.1 , V01.2 』 , BORLAN [ 21 ] 「 Turbo C 2.0 USER'S GUIDEJ, [ 24 ] 「 Turbo C 十十 1.0 USER'S GUID [ 27 ] TLSI C ー 86 Ver 3.20 / 3.30 試食版 E 』 , BORLAND BORLAND [ 22 ] fTurbo C 2.0 REFERENCE GUI [ 25 ] fTurbo C 十十 1.0 PROGRAMM ユーザ、一ズマニュアノレ』 , 工ノレ・エス・ DE 』 , BORLAND アイジャパン ER'S GUIDE 』 , BORLAND List 1 ドライプ構成の表示 (alld 「 ive. c) LiSt ( 聞 si 馴 10 ) ( - 1 ) * ( xipb->clsizel + 1 ) 事 Kdpb->sec-bYte ) ; = osmajor > = 4 ? 〆 p ト > u. d0S4. pnextdpb : 図 P ト〉 u. d0S3. pnextdpb; } while ( FP-OFF( ) ト 0xffff ) : 最後の DPB チェック ? 85 : ヨ 88 : / * 返り値内部変数領域のアト・レス 89 : 90 : * / 91 : far *getdosvar( void ) struct SREGS segs : 93 : union REGS iregs; 94 : ヨ 95 : iregs. h. 曲 : 0X52 ; intdosx( &iregs. &iregs, s ) : 98 : return( MK_FP( s s. , iregs. x. bx ) ) : ファイル検索ユーティリティ (search. c) 82 : 1 : #include く 3 iO. h 〉 2 : #include く stdlib. h> 3 : # i 1 面 e く dos. h> 4 : 5 : #ifndef 一 6 : 記 efi ー ( 町 0 ) ((void far の ( ( ( si 10 ) ( s ) くく 16 ) ー ( si 馴 ) ( 0 ) ) ) 7 : #endif / 本テ・イスク・ハ。ラメータ・フ・ロ 9 : struct ( / 事ト・ライフ・番号 ( 0 , 1 , 2 ,. 凹 si char drive; 10 : / 事 = 外番号 ( 0 , 1 , 2 ,.. 聞 si char unit; 11 : / 事ハ・イト / セクタ int sec—byte ・ 12 : クラスタサイス・ 2 ・ n -1 ( セクタ / クラスタ - 13 : si 觚 char clsizel; / 本クラスタサイス・ n 聞 si char clsize2; 14 : 予約セクタ数 ( IPL のセクタ数 ) int iplsec—size; 15 : / * FAT 数 聞 si 馴 char fatnum; 16 : / * トト・テ・イレ外リエントリ数 int dirnum; 事 / / 本テ・一タ領域開始論理セクタ番号 忸 1a8 : / * テ・一タ領域最大クラスタ番号 ( 全クラスタ数 + 1 ) int data—size; 19 : union ( 20 : 1 struct ( unsignai char fat-size; / * セクタ数 / FAT 22 : 聞 si int dir-place;/* ト・テ・イレ外リ領域開始論理セクタ番号 far / ネデハ・イス・ドライハ・の本・インタ VOid 24 : 1 メテ・イアテ・イスクリフ。タハ・イト 凹 si 觚 char 25 : 1 聞 si char diskchange; / * テ・イスク交換を示すフラク・ 26 : struct dpbstruct far *pnextdpb; 次の DPB を指す本。インタ / * 最後に変更したクラスタ番号 聞 si 馴 int 1 t ー cl : / 本空きクラスタ数 si 馴 int fræ—cl; } dos3; 30 : struct { 31 : 凹 si int fat-size; / * セクタ数 / FAT 32 : 聞 si 馴 int dir-place;/* ト・ディレクトリ領域開始論理セクタ番号 far *Xievrmd; / 本テ・ハ・イス・ト・ライハ・の本。インタ VOid 34 : メテ・イアテ・イスクリフ。タハ・イト 聞 si char 35 : 凹 si 馴 char diskchange; / * テ・イスク交換を示す万ク・ struct dpbstruct far *pnextdpb; / 本次の DPB を指すホ。インタ / * 最後に変更したクラスタ番号 int last—cl; / ネ空きクラスタ数 si int fræ-cl; 39 : 4 41 : 42 : } SDPB; 44 : typ«ief struct ( / * 内部変数領域 / ネファンクション 52h の ES:BX が指し示す領域の内容 先頭の MCB のセク・メント・アト・レス -2 46 : / * 凹 si 事 / / 事 00h DPB の先頭への本。インタ void far *Mipb; 内部 FCB フ・助クの先頭への本。インタり / * 0 曲 void far *pfcblmd ・ 48 : 事 / CIÆK デハ・イスを指すホ。インタ / * 08h void far *X)Ikdev; u)N テ・ハ・イスを指す本・インタ / 事 0Ch void far *X,01dev; 接続ト・ライフ・中で最大のハ・イト / セりタ * / / * 10h 凹 si zx-secbyt; 51 : 本 / 内部テ・イスク・ハ・ツフアの先頭アト・レス 12h 52 : void far *ldskbuf; 内部ト・ライフ・情報の先頭アト・レス / * 16h 53 : void far *Birvinf ; 不明 / 本 1 曲 54 : void far *prsvl; 純 = x , y の y / 事 1 凹 sign rsv2; 55 : 接続ト・ライフ・数 / 本 20h char drivenum; LASTDRIVE ト・ライフ・数 / ネ 21h 凹 si char 1 r ⅳ e ; LASTDRIVE=Z ならば 1 曲 59 : } SIBVAR; 60 : 61 : void prdrive( SDPB far * ) ; 62 : SIX)SVAR far *getdosvar( void ) : : int ⅲ ( void ) / * 内部変数領域のアト・レス (M)SVAR far 66 : / * 内部変数領域のアト・レス 68 : vdosvar = getdosvar(); prdrive( rnosvar->gipb ) ; / ネト・ライフ・構成の表示 69 : return( 0 ) : 73 : void prdrive( SDPB far 本〆 ) ト・ライフ・構成の表示 74 : { printf( = 外セクタ長クラスタ長 DIR 数クラスタ数テ・イスク容量 \ n ” ) ・ printf( ” 76 : do ( DPB のチェーンをたどる printf( ”記 : Xu 郷 u u % 7u % 7u % 1 u \ n ” , 78 : + ・ A' , 図 P ト > it. ( EOb->clsize1 + 1 ) 事図 p ト > sec byte, 〆 p ト i 「 n , 〆 p ト > 面ねー si 四 - 1 , / * 内部変数領域のアト・レスの取得 List 1 : #include く s i0. h > 2 : #include く string. h> 3 : #include く s lib. h 〉 4 : # i 1 面 e く dos. h> 5 : 6 : #if defined( —TURBC ) 7 : #include く dir. h> findfirst( (p), (buf), (attr) ) 9 : #define —dos—findfirst( p, attr. ・面 f ) 10 : #define _dos_findnext f indnext 11 : #define find_t ffblk ff_attr ib 12 : #define attrib 13 : #define wr_time ff_ft iæ ff fdate 14 : #define wr_date ff_fs ize 15 : #define Size ff_name 16 : #define 聞 17 : #define —A—NORMAL 0X00 FA_RInNLY 18 : #define —A-RIMLY FA_HIDDEN 19 : #define -A-HIDDEN 20 : #define —A-SYSTU FA SYSTEM FA LABEL 21 : #define _A_VOLID FA_DIREC 22 : #define _A_SUBDIR 23 : #define _A_ARCH FA_ARCH 24 : #define HARDERR-FAIL 3 25 : #define harderr 26 : #def ine hardresume hardresume 28 : int int24h( void ) : 29 : #elif defined( LSI-C ) 30 : int far int24h( void ) : 31 : #else 32 : void far int24h( void ) : 33 : #endif 34 : 35 : #ifndef MK_FP 36 : #define MK-FP(s,o) ((void far *)(((unsignai 1 。 ) ( s ) くく 16 ) ー 37 : #endif / * ハ。スの長さ ( ” d : \ ” + ハ。ス ) 38 : #define PATHLEN ( 3 + 64 ) 39 : / 本テ・イスク・ハ。ラメータ・フ・ロック 40 : typedef struct dpbstruct ( ( 0 , 1 , 2 ,. / * ト・ライフ・番号 char dmve ( 0 , 1 , 2 ,. / 本ェット番号 char unit; unsignai 42 : / 本ハ・仆 / セクタ unsigned int sec_byte; / * クラスタサイス・ 2 ・ n -1 ( セクタ / クラスタ - 1 ) unsigned char clsizel; 44 : / * クラスタサイス・ n unsigned char clsize2; / ネ予約セクタ数 ( IPL のセクタ数 ) uns igned int 46 : / ネ FAT 数 char fatnum; uns i / * トト・テ・イレ外リエントリ数 dirnum; unsigned int / * テ・一タ領域開始論理セクタ番号 面ね 1a8 ; uns i int 49 : / * テ・一タ領域最大クラスタ番号 ( 全クラスタ数 + 1 ) data-size; unsigned int union { 51 : struct { / * セクタ数 / FAT char fat_size; int dir-place;/* ト・テ・イレ外リ領域開始論理セクタ番号 far ネ図 e ⅶ d ; / * テ・ハ・イス・ト・ライハ・の本。インタ void / * メテ・イアテ・イスクリフ。タハ・イト 聞 si 馴 char ね : char diskchange; / * ディスク交換を示すフラク・ ネ / } 4 ; り / * フ。ロク・ラム上のシステム・コールの失敗 * / ネ / 新 MS-DOS プログラミング入門 95

4. 月刊 C MAGAZINE 1992年11月号

をつけなければなりません。 れてしまいます。 の複写処理により処理前のデータが破壊さ タは別の領域に保存しておかないと , 前述 タを先に処理したうえて、 , 処理済みのデー とになります。このため , 常に後側のデー タの末尾に共有点がどんどん追加されるこ 分割は再帰的に繰り返されるのて、 , デー 統合処理の詳細 トを行っていくのて、 , データを切ったりつ します。統合処理て、は経路のショートカッ 次に統合処理に適したデータ構造を検討 ほう ( 距離が短くなるほう ) を採用するよう トカットの効果を計算して , 効果の大きい ことになります。このように , ショー よりも , b-c-d をショートカットしたほうが するためには , a-c-d をショートカットする す 0Fig. 7 の場合 , 経路長をて、きるだけ短く d または b-c-d のパスをショートカットしま いるのて、 , 冗長性を排除するために , a-c- います。この図て、 , 項点 c には 2 回訪問して Fig. 7 は統合直前の経路のようすを示して 以下 , 順を追って説明していきます。 ムてもっとも難しいのが統合の処理て、す。 先ほど少し触れましたが , このプログラ 分割の過程て、ソーティングを行う都合か ら , 点列を表現するデータ構造には配列が こて、 , 点とその配列のデ 適しています。 ータ構造を Fig. 4 に示します。 こて、 , 解決しなければならないやっか いな問題がひとつあります。前述のように ふたつの領域て真ん中の点をひとっ共有す るように分割するのて、すが , 共有状態を保 とうとすると , 真ん中の点データを移動て、 きなくなります (Fig. 5 ) 。その対策として , やや技巧的になりますが , 真ん中の点をデ ータ末尾にコヒ。ーすることにします。こう すれば , その後のステップてソート可能に なりますが , 今度はデータの処理順序に気 27 : / * 43 : ) ; 48 : { 56 : } * 実行法 . A>tcc -DDISPLAY tsp. c graph. c graphics. lib * コンパイル法 : (Turbo C + + 専用です ) * 作成 : 松田晋 ・ / * file = tsp. c TSP プログラム List 6 1. 3 : 5 : 8 : 10 : 11 : 12 : 13 : 14 : 15 : 20 : 21 : 22 : 23 : 24 : 26 : 28 : 29 : 30 : 31 : 32 : 33 : 34 : 35 : 36 : 38 : 40 : 41 : 42 : 44 : 46 : 49 : 50 : 51 : 52 : 53 : 54 : 55 : 57 : 59 : 60 : 62 : 64 : 66 : 68 : 69 : 70 : * 注意 A>tsp 頂点数 実行が終了したらリターン・キーを押すこと 実行時にはカレントディレクトリに PC98. BGI が必要です。 16 : #include く stdio. h> 17 : #include く stdlib. h> 18 : #include く math. h> / * グラフィックの初期化 * / void init—graphics(void) ; / * グラフィックの終了 * / void flush—graphics(void) ; VOid draw 1 ine(int C010r , int xl, int YI, int int (2) : VOid clear_screen(void) : 25 : #define MAX—XY 1500 * 型の宣言 typedef int unit—t; typedef struct POint point—t; typedef struct link 1 ink—t; enum {vertical, horizontal); struct point ( unit—t x, y; 39 : struct 1 ink { point—t xy; link t *prev; link t *next; 45 : / * 工ラー処理付きの 110C 47 : void *xalloc(size—t n) void *p; P = 皿 110C ( n ) ; ニ NULL) { fprintf(stderr, exit(l); return p : sorry memory ful l%n") ; 58 : / * 縦長か横長かを返す int direction(point_t xy[], int n) unit_t min—x, max—x, nnn—y, mx—y, X, y; int i ; min—x = max-x = XYCO]. x; min—y = max—y = XYCO]. y; for (i = 1 ; i く n; i + + ) { x = xy[i]. x; if (x く min x) mn_x = x; else if(x > max—x) max X = x; y = xy[i]. y; if (y く min—y) else if(y 〉 max-y) 80 C MAGAZINE 1 2 11

5. 月刊 C MAGAZINE 1992年11月号

Fig. 7 Window とメッセージの概路 キーボード Fig. 8 MSG 構造体の定義 typedef struct tagMSG { hwnd; HWND WORD message; WOR D WParam : LONG 1 Param ; DWORD time; POI NT pt; } MSG; / / メッセージが送られるウインドウのハンドル / / メッセージ識別子 / / ワードバラメータ / / ロングパラメータ / / メッセージがキューにポストされた時刻 / / メッセージがポストされたときのマウスの座標 マウス タイマ Windows Fig. 9 PO 爪 T 構造体の定義 typedef s truct tagP01 NT ( / / X 座標 int / / Y 座標 i nt ) POINT; アプリケーション アプリケーション るのか , マウスの情報て、あるのかはわから よ ! ) や WM DESTROY( ウインドウが破壊 ージループの解説に移れるようになった。 ない ( わざと選択的に待っこともて、きるが , される ! ) のように , WM て、始まる名前が while 文の条件式中の GetMessage が , メ あまり一般的て、はない ) 。 ッセージを受け取る関数だ ( 概要を Table 与えられている。 Windows て、は , そのような情報をメッセ 14 に示す ) 。 GetMessage は , 受け取ったメ 続くメンバ , wParam および IParam は , ージという概念て、考える。キーポードやマ サプメッセージ , すなわちウインドウメッ ッセージが , アプリケーションを終了する ウスの操作などは , メッセージの形に変換 必要があることを指示する WM QUIT て、あ セージに対する追加情報が格納される。 され , Windows システムに送られる。その れば , アプリケーションを終了すべきて、あ こに格納される内容は , 各メッセージによ メッセージは , アプリケーションに読み出 ることを示す FALSE を返す 0FALSE は 0 と って異なる。たとえば , 文字入力を表す W され , そのメッセージに対して何らかの処 して定義されているのて、 , while ループは , M CHAR メッセージの場合 , 入力された文 理を行うというのがⅥⅱ ndows プログラムの 字の ASCII コードがサプメッセージて、ある w 繰り返しを終了する。 基本的な構造てある。 Windows とメッセー これがメッセージループの骨格だ。 Param に格納される。 ジの関係の概略を Fig. 7 に示す。 while (GetMessage(&msg, NULL' 0 , 0 ) ) { 最後のふたつのメンバは , メッセージ発 TranslateMessage (&msg) ・ 生時の状況を示すものて、ある。メンバ time メッセージを表す MSG 構造体 DispatchMessage(&msg) ・ には , メッセージがメッセージキューに入 れられた時間が , メンバ pt には , その時点て、 第 2 引数は , アプリケーションに属するす Windows の動作の根本となるのがメッセ のマウス座標が格納される。なお , 座標を べてのウインドウのメッセージを得るため ージて、あることがわかったが , そのメッセ 表す POINT 構造体は , Fig. 9 に示すように ージは , プログラム上て、はどのように表現 に NULL を指定している。第 3 引数 , 第 4 引 定義されている。 されるのだろうか。メッセージは , Fig. 8 のよ 数は受け取るメッセージの範囲を制限する うに定義される MSG 構造体として表される。 メッセージループ。。 ためのものて、あるが , 通常はすべてのメッセ ージを受け取るのて、 , 両方とも 0 を指定する。 MSG 構造体の各メンバを見ていこう。 これて、 , 先ほど名前だけ紹介した GetMessage が受け取ったのが , WM QU 最初のメンノ *hwnd は , メッセージの送り ' メッセ 先て、あるウインドウを表す。 TabIe 14 GetMessage の概要 2 番目のメンバ message は , メッセージ識 GetMessage 別子て、あり , どのようなイベントが発生し * IpMsg, HWND hWnd, WORD wMsgFilterMin• 形式 BOOL GetMessage(LPMSG たのかをアプリケーションに知らせる。 WORD wMsgFilterMax) : れは , ウインドウメッセージと呼ばれるも 解説 アプリケーションキューからメッセージを受け取り , ゆ Msg の指す LPMSG 構造体テータに , メ ッセージを格納する。 のて、 , <windows. h> には , すべてのウイン hWnd には , メッセージを受け取るウインドウの識別八ンドル ( アプリケーションに属するすべ ドウメッセージが定義されている。ウイン てのウインドウのメッセージを得るには NUL し ) を指定する。 戻り値 メッセージが WM QU げであれば 0 ( FALSE ) を , そうでなければ非ゼロの値を返す。 ドウメッセージには , WM PAINT ( ウイン 関連項目 PeekMessage, WaitMessage ドウの描画内容が破損したのて、 , 再描画せ 56 C MAGAZINE 1 2 11

6. 月刊 C MAGAZINE 1992年11月号

実践アルゴリズ壓路解法のテクニック 割は O ( n ) の計算量て、行えます。一方 , ソー ライプラリ関数を使える場合は , とりあえ 率の高いアルゴリズムを用いるほうが賢明 トに要する時間は O ( nl 。 gn ) て、すから大き ず既存の関数を使って実装しておき , 本当 て、す。性能の評価については , 最後にまと な違いて、す。しかし , qsort のような既存の に効率が悪いことが証明されてからより効 めて書くことにします。 Fig. 8 環状双方向リスト 環状双方向リストの図 Fig. 7 ショートカットノヾスの選択 typedef struct link link—t; struct link ( point—t xy ; link—t *prev; / * 順方向ポインタ * / link—t *next; / * 逆方向ポインタ * / a ー c ー d を a ー d にショートカットするよりも b ー c ー d を b ー d にショートカットしたほうが 経路は短くなる。 List 3 マージ処理部 分割統治 List 5 0 0 0 8 る す ・う 0 0 算 果 す る 効 & & 指 の ジ X O X 一 点 ッ ッ 有 x カ カ マ ・ 1 、 0 共、 2 を 路釀 カ 0 A 0 ョ ョ 00 1 人・・ー、 経 00 1 よ′ー、 シ 1 ・ 4 11 人 》 1- つ 00 4 0 れ 0 っー 8 9 0 1 人っっリ -4 - -0 6 叮ー 8 0 》 0 ・ 1 つな 00 4 LD 6 ー 8 0 11 りっ 0 4 【 0 6 っー 8 9 0 1 人 11 ・ 1 イ 1 、 1 1 人 1 人 1 人 1 ・・ 1 1 っ 0 りっ編っ臨りなりなっりりなれ 0 っ 0 っ 0 っ 0 っ 0 っ 0 れ 0 00 れ 0 00 4 4 1 : / * 分割統治 3 : link t *divide and_conquer(point_t xy[], int n) 5 : int m; 6 : 1 ink_t *p, *q; 7 : point_t node_xy; 8 : / * 自明な場合 ( 三角形以下の場合 ) 9 : 10 : if (n ← 3 ) 11 : 12 : return set_link(xy, n); 13 : m = divide(xy, n); node-xy ニ xyCn] = xyCm] ; 14 : 15 : / * 再帰的な分割 ( 後側を先に ) 17 : P = divide_and_conquer(&xy[m + 1 ] , n ー m) ; q = divide and_conquer(&xy@], m + 1 ) ; 20 : 21 : return merge(), q, &node—xy) ; / * 統合 * / 22 : } / * 分割 * / / * 共有点の複写 * / 分割関数 divide List 4 1 : / * 分割処理 2 : 3 : int divide(point—t ロ , int n) = horizontal) if (direction(xy, n) 5 : qsort(xy, n, sizeof(xyCO]), comp-h) : 6 : 7 : else qsort(xy, n, sizeof(xy[0]), comp—v) : 8 : 9 : return n / 2 ; 実践アルゴリズム戦略解法のテクニック 79

7. 月刊 C MAGAZINE 1992年11月号

分割したほうがよいともいわれます。後者 の具体例としてはクイックソートをあげる ことがて、きます。クイックソートは各分割 がちょうど半々の分割になるときが最速て、 , 逆に 1 : n— 1 の分割が続くときにもっとも効 率が悪くなるのて、した。 以上の経験則をふまえ , 領域が縦長なら ば横に分割し , 横長ならば縦に分割するこ とにします。もちろん , 分割後の点の個数 は極力均等になるように分割します。この ルールにより分割した例を Fig. 3 に示しま こまて、説明した内容を疑似コードて、表 現すると List 1 のようになります。まだ分割 や統合の詳細については検討していません が , これらはデータ構造を決めながら徐々 はありません。以前に紹介した「 n 番目のデ ータを求める」アルゴリズムを用いると , 分 14 : ) 1 : 縦長・横長チェック ( 領域 ) 縦長・横長のチェック法 List 2 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : 11 : 12 : 13 : mn_x max_x max—Y 領域の巾 両域内の点の x , y 座標値の 最小・最大値を求め、 mln_x, max X, mn_y, max_y max_x ー mm_x, に代入する 領域の高さ = max-y ー min-y; if ( 巾 > 高さ ) return 横長 , else return 縦長 : Fig. 4 点列のテータ構造 } point_t , unit t x, y , typedef struct { typedef int unit t , point t xy [MAX XY]: に詳細化していくことにします。 分割処理の詳細 の qsort を使用て、きます。実はこの部分も改 ものて、 , ソーティングにはライプラリ関数 ておいてソート結果を半々に分けるという それは点列を横 ( または縦 ) 方向にソートし これもいちばん単純な方法を取りましよう。 次に横分割ないし縦分割のしかたて、すが , 皆さんへの宿題としましよう。 座に求めることがて、きますが , この改良は 割前の最大・最小値と分割点の座標から即 2 ) 。実はいちいちチェックしなくても , 分 座標値の最小値・最大値から求めます (List します。縦長・横長のチェックは , 単純に かをチェックし分割の方法を決めることに ように , 分割に先立って領域が縦長か横長 まず分割について考えます。 List 1 に示す 構造について検討します。 ながら , これらの方法を行いやすいデータ この節て、は , 分割や統合の詳細を検討し 78 C MAGAZINE 1 2 11 良がて、きます。 分割するためには , 何もソートする必要 / * 座標の型 * / / * 点型の宣言 * / / * 点列を表す配列 * / Fig. 5 真ん中の点を共有すると共有テータを移動できない 領域 1 共有 真ん中の点を共有した状態を保とうとすると , 共有テータを移動できない ( 次のステップてソート不可 ) Fig. 6 真ん中の点をテータ末尾にコピーする 領域 1 領域 2 領域 2 複写 共有テータをテータ末尾にコピーすると , 後のステップでソート可能になる。 そのかわり , 後のテータを先に処理しなけれはならない。

8. 月刊 C MAGAZINE 1992年11月号

五ロ どこて、クリックされたかによってどのよう n はイベントが発生した時間 ( システムが起 入力されたキーコードと文字コードを示し , な処理をするかを決定します。 動されてからの時間。 1 / 60 秒単位 ) て、す。 ウインドウ関係のイベントて、は対象となる keyDown と autoKey はキー入力のイベン mod ⅲ ers はイベントが発生したときに押 ウインドウへのポインタが入ります。たと されていたキー ( ーキーやキー トて、す。これらのイベントに対しては , ま えば updateEvt て、は再描画が必要なウインド ずーキーが同時に押されていたかど など ) の状態などを示します。 keyDown イベ ウを示します。 うかを調べ , 押されていたならメニューの ントを得たときに modifiers をチェックし , プログラムの構造 もしも一キーが押されていれば , そ キーポードショートカットとして処理し ( メ ニューマネージャの MenuKey ( ) を呼び出 れはキーポードショートカットて、あるとわ し ) ます。ーキーが押されていないな かります。同様に , キーを押しながら Macintosh のアプリケーションはイベント ら , 入力された文字はアプリケーションが マウスをクリックすると , いつもとは異な を処理し続けるようにプログラムされます。 処理します。 る動作をするといったプログラムを作るこ 簡単には List 2 のようなプログラムになりま updateEvt はウインドウ内のデータを再描 ともて、きます。また , what が activateEvt の す。このリストの中の Boolean は真偽値を示 画しなければならないことを示しています。 ときにはウインドウがアクテイプにされる すために使われる型 , true は真を false は偽 オーバラップしたウインドウの階層構造が のか , それともアクテイプて、なくなるのか を示す値て、す。このあたりの名前は Pascal 変化すると , 今まて、は上のウインドウに覆 を示します。 に由来しています。 われて見えなかった部分が見えるようにな message はイベントによって異なる意味を BooIean の変数 done はユーザが F ⅱ e メニュ 持ちます。キーポード関係のイベントて、は ったかもしれません。こんなときにウイン ーの「 Quit 」を選択したときに true になります ドウマネージャは updateEvt を生成します。 EventRecord の定義 ウインドウの中に何を表示するかはアプリ ケーションの間題て、すから , 責任を持って 再描画しなければなりません。 activateEvt は updateEvt と同様にウイン ドウの階層構造の変化に応じて生成される イベントて、す。いちばん手前に出てくるウ インドウに対してはアクテイプになったよ というイベントが , これまて、いちばん手前 にあったウインドウに対してはアクテイプ て、なくなるよというイベントが生成されま す。アプリケーションはイベントに応じて 各ウインドウのスクロールバーを表示した り消去します。 nullEvent はイベントキューには現在未処 理のイベントがないことを示します。 , こて、はふれませんが , このほかにもデ イスクインサートイベントや MultiFinder 上 てのアプリケーションがスイッチした を示すイベントなどがあります。 EventRecord イベントの内容を示す構造体 EventRec 。 rd は List 1 のように定義されています。 wh at はイベントの種類を示します。 where はイ べントが発生したときのマウスの位置を示 し , 座標を表す Point 型をしています。 whe List 1 struct { / * event * / short what : long message; event message * / / * ticks s ince startup * / 10 when; Point where; mouse * / / * modifier flags * / short *. ifiers; } EventRecord; イベント駆動プログラム B81 n done; void main() 各マネージャを初期化する done = false; while (!done) { イベントをキューから取リ出す if ( 処理すべき ) イベントを処理する List 2 Macintosh プログラムの構造 1 : B81 田 n done; 2 : EventRecord myEvent; 3 : 4 : void handleAppleCh0ice(short item) / * アップルメニューの処理 * / switch (item) { 6 : case AboutItemID: / * About が選ばれた * / 7 : タイトルなどの表示する 8 : 9 : break : default: 10 : デスクアクセサリを実行する 11 : break; 12 : 14 : ) List 3 C 言語雑学講座 127

9. 月刊 C MAGAZINE 1992年11月号

deldin. c List ・・・ ) ということてす。その事情を図示する と , Fig. 1 のようなもんてしようか ( 再帰コ ールを 2 レベルやっている場合 ) 。 て , 関数 rmvdir ( ) を作ってから , 後から 気がついたのてすが , この関数の中てファ イルに対して実行している処理て、ある remo ve ( ) ( 75 行 ) と , ディレクトリに対して実行 している rmdir ( ) ( 81 行 ) を , 関数ポインタと して引数として渡してやれば , この関数の 汎用化がて、きるのて、す。 名前は未定て、すが , この汎用関数 foofoo ( ) は , ディレクトリバス名 , 関数ポインタ 1 , 関数ポインタ 2 , 計三つの引数を取り , 指定のディレクトリとそのサプ ~ サプサプ ディレクトリに含まれているすべてのファ イルに対して関数ポインタ 1 て指定される処 理を行ない , またディレクトリ ~ サプディ レクトリに対しては , 関数ポインタ 2 て、指定 される処理を行ないます。関数ポインタ 2 と して NULL を渡せば , ディレクトリ ~ サプ ディレクトリに対する処理は行なわれませ ん。 もちろん , 汎用関数に書き直すのが面倒 なかたは , 関数 rmvdir( ) ( この名前だけは変 えたほうが良いて、しよう ) の中の関数コール (rmvdir( ) , remove( ) , rmdir( ) の三つ ) を適宜書き換えれば , その都度の自分の目 的のために使えます。 一般性に乏しい MS - DOS の ティレクトリ仕様 あと , 細かい点を 2 ~ 3 。 dirsyntax() という関数は , 引数として渡 された文字列がディレクトリバス名て、ない か , または , カレントディレクトリならば , ゼロを返します。このゼロは , 、、ディレクト リの指定が間違い〃という意味てす。カレ ントディレクトリを削除してしまったら , コンピュータの実行環境が , 梯子を外され た植木屋さん ( or 屋根職人 ) のような始末に なってしまいます。 1 : / * deldir. c : remove directory * / 2 : / * Jul. 23 , 1992 by hiwa * / 3 : 4 : #include く stdiO. h> 5 : #include く dir. h> 6 : #include く a110C. h 〉 7 : #include く dos. h> 8 : #include く string. h 〉 9 : 10 : void rmvdir( char *dirnam ) : 11 : int dirsyntax( char *name ) ; 12 : 13 : char basedir[ 80 ] ; 14 : 15 : void main( int argc, char **argv ) 16 : { int i; 18 : if( argc く 2 ) { 19 : printf( ” *nUSAGE: deldir dirname%n ” ) ; 20 : printf( . remove directory including subdirectories. exit( 1 ) ; 22 : 23 : 24 : 25 : 26 : 28 : 29 : 30 : 31 : 32 : 33 : 34 : 35 : 38 : / * 39 : 下請実働関数 * / 40 : VQid rmvdir( char *dirnam ) 41 : { char path[ MAXPATH ] , drive[ MAXDRIVE ] , dirC MAXDIR ] , 42 : nameC MAXFILE ] , extC MAXEXT ] ; 43 : char curpathC MAXPATH ] ; 44 : 45 : char *P ; 46 : int findend; 47 : struct ffblk fb; 48 : Size t len,• 49 : 50 : len = strlen( dirnam ) : if( dirnamC len ー 1 ] ! = ' \ \ ' ) { / * fnsplit ( ) が正しく動作するために * / 51 : dirnam[ len ] / * 末尾を確実に ' \ ' にする 52 : dirnamC len + 1 ] 53 : 54 : 55 : 56 : 58 : 59 : 60 : 63 : 64 : 65 : 66 : ニ 1 ; / * point second arg * / 1 while( --argc > 0 ) { if( ! dirsyntax( argvC i ] ) ) { printf( "Directory specification IS invalid: Xs*n*n", argv[ i ] ) ; )else{ strcpy( basedir, argv[ i ] ) ; / * rmvdir ( ) が加工するため余裕のある文字列を渡す * / rmvdir( basedir ) ; 十十 1 ; fnsplit( dirnam, drive, dir, NULL, NULL ) ; fnmerge( path, drive, dir, findend = findfirst( path, &fb, FA—DIREC ) ; while( ! findend ) { if( fb. ff_attrib & FA_DIREC ) { / * テ・イレクトリ * / if( fb. ff_name[ 0 ] ! = and strcpy( curpath, dirnam ) ; strcat( curpath, fb. ff_name ) ; rmvdir( curpath ) ; findend = findnext( &fb ) ; 108 C MAGAZINE 1992 11

10. 月刊 C MAGAZINE 1992年11月号

合。。 thi ~. 。、 0 ) が最初 0 = 起動したときのら 行う初期処理て、ある。 て、 W0d010 引、 ウ→ードウクラを表す 体のオプジ = クトて、ある。その WNDCLA S 型は , Fig. 4 のように定義されている 各メ , , の初期化に 0 、て , 簡単に見、 ンスタンスだけて、ある。よって , プログラ 「時計」を 3 個起動した場合 , 各時計は , その ム中の , コード部を共用する。 ただし , それぞれは独立したアプリケー ションなのて、 , それをインスタンスと呼ぶ のて、ある。この場合 , 「時計アプリケーショ ンのインスタンスが 3 個起動している」状態 となる。もちろん , 各インスタンスには , それぞれの背番号 = インスタンスハンドル が与えられる。 「時計 ( 1) 」 , 「時計②」 , 「時計 ( 3 ) 」や , そ のほかのアプリケーションを起動したとき の , それぞれの hlnstance, hPrevInstance がどのようになるかの例を Fig. 3 に示す。 F ig. 3 からわかるように , hPrevInstance は , ひとつ前に起動された同一アプリケーショ ンのインスタンスハンドルを受け取るのて、 ある。もちろん , 初めて起動されたときは , 0 となることも , 図からわかるて、あろう。 本プログラムては , lpszCmdParam は利 用していないのて、 , ここて、は簡単に紹介す る程度にとどめよう。 lpszCmdParam は , コマンドライン引数を格納する文字列への far'* インタて、ある。一般的な C 言語 main 関 数の引数 char * * argv の代替物と思ってい ただきたい 最後の nCmdShow には , 初期のウインド ウ表示方法が指定される。この引数は , そ のアプリケーションを起動したプログラム によって与えられるものて、あり , 通常 1 ( 通 常起動 ) もしくは 7 ( アイコン起動 ) の数値が 指定される。このパラメータについては , ShowWindow の説明の際に , 具体的に解説 する。 if (!hPrevlnstance) { / * wndclass の初期化 * / RegisterCIass (&wndclass) ・ のところは , そのアプリケーション ( この場 Fig. 3 アプリケーションの起動とインスタンス八ンドル 旱半 時間 ( 起動順序 ) アプリケーション hP 「 evlnstance hlnstance Fig. 4 WNDCLASS 型の定義 typedef struct tagWNDCLASS ( style; WORD LONG (FAR PASCAL *lpfnWndProc) ( ) : cbClsExtra; i nt cbWndExtra ; int HAN DLE hl ns tance ; HICON hlcon; HCURSOR hCursor; HBRUSH hbrBackground; LPSTR lpszMenuName : LPSTR lpszClassName; } WNDCLASS; 加イ ジの加 シスの ロラへ プクス ウウンル シ名 ルドドタ一ンルラ一名 インンスュコソブュス タイインジィ一景ニラ スウウィモアカ背メク TabIe 4 クラススタイル 解説 識別子 バイト境界にウインドウのクライアントエリアを揃える ( x 軸方向 ) CS BYTEALIGNCLIENT バイト境界にウインドウを揃える ( x 軸方向 ) CS BYTEALIGNWINDOW ウインドウクラスに自身のティスプレイコンテキストを与える CS CLASSDC ( 複数のインスタンスでティスプレイコンテキストを共有する ) ウインドウにダブルクリックメッセージを送る CS DBLCLKS ウインドウクラスが , アプリケーションのグローノヾルクラスであることを指定する CS GLOBALCLASS 水平方向のサイズが変更されると , ウインドウ全体を再描画する CS HREDRAW システムメニューの【クローズ】オプションを使用禁止にする CS NOCLOSE 各ウインドウインスタンスに , それぞれティスプレイコンテキストを与える CS OWNDC ウインドウクラスに , 親ウインドウのティスプレイコンテキストを与える CS PARENTDC ウインドウによって隠されたスクリーンイメージを保存する CS SAVEBITS 垂直方向のサイズが変更されると , ウインドウ全体を再描画する CS VREDRAW Step4 ウインドウクラスの登録 Windows 上の各ウインドウは , ウインド ウの性質を表現するウインドウクラスに基 づいて作成される。ウインドウクラスを作 成するには , RegisterClass によってウイン ドウを登録する。もっとも , ウインドウク ラスを登録する必要があるのは , 最初のイ 50 C MAGAZINE 1992 11