MAKEWPARAM, HIWORD, LOWORD マクロとは?

マクロの定義は次です。


#define LOWORD(l)           ((WORD)((DWORD_PTR)(l) & 0xffff))
#define HIWORD(l)           ((WORD)((DWORD_PTR)(l) >> 16))
#define MAKELONG(a, b)      ((LONG)(((WORD)((DWORD_PTR)(a) & 0xffff)) | ((DWORD)((WORD)((DWORD_PTR)(b) & 0xffff))) << 16))
#define MAKEWPARAM(l, h)      ((WPARAM)(DWORD)MAKELONG(l, h))

MAKEWPARAM, HIWORD, LOWORD, MAKEWORD などのマクロ郡では、「下位ワード」「上位ワード」 等の言葉が出てきます。

コードを見て一目瞭然という方は問題ないでしょうが、いまひとつピンと来ない人のために、 実験をしてみました。

テストコードはこちら。

#include <windows.h>
#include <stdio.h>


void PrintHexDump (DWORD length, PBYTE buffer) {
    
	DWORD i,count,index;
	CHAR rgbDigits[]="0123456789abcdef";
	CHAR rgbLine[100];
	char cbLine;

	for(index = 0; length; length -= count, buffer += count, index += count) {

		count = (length > 16) ? 16:length;

		sprintf(rgbLine, "%4.4x  ",index);
		cbLine = 6;

		for(i=0;i<count;i++) {
			rgbLine[cbLine++] = rgbDigits[buffer[i] >> 4];
			rgbLine[cbLine++] = rgbDigits[buffer[i] & 0x0f];
			if(i == 7) {
				rgbLine[cbLine++] = ':';
			} 
			else {
				rgbLine[cbLine++] = ' ';
			}
		}

		for(; i < 16; i++) {
			rgbLine[cbLine++] = ' ';
			rgbLine[cbLine++] = ' ';
			rgbLine[cbLine++] = ' ';
		}

		rgbLine[cbLine++] = ' ';

		for(i = 0; i < count; i++) {
			if(buffer[i] < 32 || buffer[i] > 126) {
				rgbLine[cbLine++] = '.';
			} 
			else {
				rgbLine[cbLine++] = buffer[i];
			}
		}

	        rgbLine[cbLine++] = 0;

		printf("%s\n", rgbLine);

    }
    

}


void print_desc ( char* s ) {

	HANDLE hStdOut = (HANDLE) GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO csbi;

	::ZeroMemory(&csbi, sizeof(CONSOLE_SCREEN_BUFFER_INFO));

	if(!GetConsoleScreenBufferInfo ( hStdOut, &csbi) ) {
		printf("GetConsoleScreenBufferInfo failed. %u\n", GetLastError());
		return;
	}
		
	SetConsoleTextAttribute ( 
		hStdOut,
		FOREGROUND_GREEN | FOREGROUND_INTENSITY
	);

	printf("%s\n", s);
	

	SetConsoleTextAttribute ( hStdOut, csbi.wAttributes );
	
}


void print_value_addr( char* s, int size, void* pv) {

	printf( "[%s 0x%p]\n", s, pv );
	PrintHexDump( size, (PBYTE) pv );
	char* pch = (char*) pv;
	for( int i=0; i < size; i++ ){
		printf( "  %p - %c\n", pch, *pch );
		pch++;
	}

}


int main(int argc, char* argv[]){

	WORD w1 = MAKEWORD('a','b');

	print_desc(" w1 = MAKEWORD('a', 'b')");
	print_value_addr ( "w1", sizeof(WORD), &w1 );

	WORD w2 = MAKEWORD('c','d');
	
	print_desc(" w2 = MAKEWORD('c', 'd')");
	print_value_addr ( "w2", sizeof(WORD), &w2 );
	
	
	WPARAM wParam = MAKEWPARAM( w1, w2 );

	print_desc(" wParam = MAKEWPARAM(w1, w2)");

	print_value_addr ( "wParam", sizeof(DWORD), &wParam );
	
	WORD w3 = LOWORD( wParam );
	WORD w4 = HIWORD( wParam );

	print_value_addr ( "LOWORD(wParam)", sizeof(WORD), &w3 );
	print_value_addr ( "HIWORD(wParam)", sizeof(WORD), &w4 );
		
	return 0;
}

MAKEWPARAM マクロで WPARAM 値 wParam を作っています。 WPARAM は DWORD (ダブル・ワード) で、4バイトなのですが、それを構成する WORD は MAKEWORD で作っています。

MAKEWPARAM は (「下位ワード」, 「上位ワード」) です。 一方、MAKEWORD は ( 「下位バイト」, 「上位バイト」) です。

> test1
 w1 = MAKEWORD('a', 'b')
[w1 0x0012FF38]
0000  61 62                                            ab
  0012FF38 - a
  0012FF39 - b
 w2 = MAKEWORD('c', 'd')
[w2 0x0012FF2C]
0000  63 64                                            cd
  0012FF2C - c
  0012FF2D - d
 wParam = MAKEWPARAM(w1, w2)
[wParam 0x0012FF30]
0000  61 62 63 64                                      abcd
  0012FF30 - a
  0012FF31 - b
  0012FF32 - c
  0012FF33 - d
[LOWORD(wParam) 0x0012FF3C]
0000  61 62                                            ab
  0012FF3C - a
  0012FF3D - b
[HIWORD(wParam) 0x0012FF34]
0000  63 64                                            cd
  0012FF34 - c
  0012FF35 - d

以上から下位バイト、下位ワードに値をセットすることは、 アドレスの小さい側にデータを詰めてセットすることに他ならないことが確認できます。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説