win32day10-组合框/列表框/滚动条/控件的自绘制

Posted 吴英强

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了win32day10-组合框/列表框/滚动条/控件的自绘制相关的知识,希望对你有一定的参考价值。

组合框 ComboBox

  1 组合框的样式

    1.1 简单组合框  CBS_SIMPLE

    1.2 下拉式组合框 CBS_DROPDOWN

       能输入或者从下拉列表中选择

    1.3 下拉列表式组合框 CBS_DROPDOWNLIST

       只能从下拉列表中选择  

  2 组合框的使用 

2.1 组合框的创建

      窗口类名称是 COMBOBOX, 使用CreateWindow

      创建, 创建时要注意窗口高度(弹出的列表).

    2.2 增加选项

      CB_ADDSTRING/CB_INSERTSTRING

      CB_ADDSTRING: WPARAM0不使用, LPARAM

                    是添加字符串的地址

    2.3 删除选项

      CB_DELETESTRING 删除指定选项

      CB_RESETCONTENT 清空所有选项

    2.4 选择

      CB_GETCURSEL 获取被选择项

      CB_SETCURSEL 设置当前的选择项

      CB_SELECTSTRING 设置选择指定的字符串所对应的项

    2.5 查找

      CB_FINDSTRING 根据指定的字符串,找到对应

                    项的索引

         1)大小写不敏感

         2)字符串和选项从左到右匹配.

         3)选项包含字符串即可

    2.6 获取选项或者被选择字符串

       CB_GETLBTEXT 获取选项的字符串

       WM_GETTEXT   获取被选择到窗口的字符串

       

    2.7 选项的数据

       可以将自定义数据信息,在选项中设置和获取.

       CB_SETITEMDATA 将数据保存到选项中

       CB_GETITEMDATA 从选项当中获取数据

       

    2.8 目录显示

       CB_DIR 将指定路径下的文件和路径信息

          显示在ComboBox当中

          wParam - 显示的类型

          lParam - 路径字符串地址

          

    2.9 通知消息

      通过WM_COMMAND消息,通知父窗口.

      CBN_SELCHANGE 当窗口的选项发生变化的

           情况下,通知父窗口.

// WinComboBox.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "stdio.h"
#include "resource.h"

HINSTANCE g_hInst = NULL;

void OnCreate( HWND hWnd, UINT nMsg,
			  WPARAM wParam, LPARAM lParam )
	//简单组合框的创建
	CreateWindow( "COMBOBOX", "SIMPLE",
		WS_CHILD|WS_VISIBLE|CBS_SIMPLE,
		50, 50, 120, 300, hWnd, 
		(HMENU)1001, g_hInst, NULL );
	//下拉式组合框的创建
	CreateWindow( "COMBOBOX", "DROPDOWN",
		WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_DROPDOWN,
		200, 50, 120, 300, hWnd,
		(HMENU)1002, g_hInst, NULL );
	//下拉列表式组合框的创建
	CreateWindow( "COMBOBOX", "DROPDOWNLIST",
		WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_DROPDOWNLIST,
		350, 50, 120, 100, hWnd,
		(HMENU)1003, g_hInst, NULL );


void OnAdd( HWND hWnd )
	//获取COMBOBOX窗口句柄
	HWND hSimple   = GetDlgItem( hWnd, 1001 );
	HWND hDropDown = GetDlgItem( hWnd, 1002 );
	HWND hDropList = GetDlgItem( hWnd, 1003 );
	//添加多个选项
	CHAR szText[] = "ComboBox 0";
	for( int nIndex=0; nIndex<10; nIndex++ )
		//添加选项
		LRESULT nItem = SendMessage( hSimple, 
			CB_ADDSTRING, 0, (LPARAM)szText );
		//设置项的数据
		SendMessage( hSimple, CB_SETITEMDATA,
			nItem, 100+nIndex );

		SendMessage( hDropDown, CB_ADDSTRING, 
			0, (LPARAM)szText );
		SendMessage( hDropList, CB_ADDSTRING, 
			0, (LPARAM)szText );
		//改变选项内容
		szText[9]++;
	


void OnDel( HWND hWnd )
	//获取COMBOBOX窗口句柄
	HWND hSimple   = GetDlgItem( hWnd, 1001 );
	HWND hDropDown = GetDlgItem( hWnd, 1002 );
	HWND hDropList = GetDlgItem( hWnd, 1003 );
	//删除指定项
	SendMessage( hSimple, 
		CB_DELETESTRING, 5, 0 );
	SendMessage( hDropDown, 
		CB_DELETESTRING, 5, 0 );
	SendMessage( hDropList, 
		CB_DELETESTRING, 5, 0 );


void OnReset( HWND hWnd )
	//获取COMBOBOX窗口句柄
	HWND hSimple   = GetDlgItem( hWnd, 1001 );
	HWND hDropDown = GetDlgItem( hWnd, 1002 );
	HWND hDropList = GetDlgItem( hWnd, 1003 );
	//清空所有项
	SendMessage( hSimple,   CB_RESETCONTENT, 0, 0 );
	SendMessage( hDropDown, CB_RESETCONTENT, 0, 0 );
	SendMessage( hDropList, CB_RESETCONTENT, 0, 0 );


void OnSelect( HWND hWnd )
	//获取COMBOBOX窗口句柄
	HWND hSimple   = GetDlgItem( hWnd, 1001 );
	HWND hDropDown = GetDlgItem( hWnd, 1002 );
	HWND hDropList = GetDlgItem( hWnd, 1003 );
	//获取和设置选择项
	LRESULT nSel = 
		SendMessage( hSimple, CB_GETCURSEL, 0, 0 );
	//获取数据
	LRESULT nValue = SendMessage( hSimple, 
		CB_GETITEMDATA, nSel, 0 );
	CHAR szInfo[260] =  0 ;
	sprintf( szInfo, "%d", nValue );
	MessageBox( NULL, szInfo, "WinCombo", MB_OK );
	
	//设置选择项
	SendMessage( hDropDown, CB_SETCURSEL, nSel, 0 );
	CHAR szText[] = "ComboBox 5";
	SendMessage( hDropList, CB_SELECTSTRING, 
		-1, (LPARAM)szText );


void OnFind( HWND hWnd )
	//获取COMBOBOX窗口句柄
	HWND hSimple   = GetDlgItem( hWnd, 1001 );
	HWND hDropDown = GetDlgItem( hWnd, 1002 );
	HWND hDropList = GetDlgItem( hWnd, 1003 );
	//查找字符串
	CHAR szText[] = "ComboBox 5";
	LRESULT nFind1 = SendMessage( hSimple, 
		CB_FINDSTRING, -1, (LPARAM)szText );
	SendMessage( hDropDown, CB_SETCURSEL,
	   nFind1, 0 );
	SendMessage( hDropList, CB_SETCURSEL,
	   nFind1, 0 );


void OnPath( HWND hWnd )
	//获取COMBOBOX窗口句柄
	HWND hSimple   = GetDlgItem( hWnd, 1001 );
	HWND hDropDown = GetDlgItem( hWnd, 1002 );
	HWND hDropList = GetDlgItem( hWnd, 1003 );
	//显示目录
	CHAR szPath[MAX_PATH] = "C:\\\\*.*";
	SendMessage( hSimple, CB_DIR,
		DDL_DIRECTORY|DDL_ARCHIVE,
		(LPARAM)szPath );
	SendMessage( hDropDown, CB_DIR,
		DDL_DIRECTORY|DDL_ARCHIVE,
		(LPARAM)szPath );
	SendMessage( hDropList, CB_DIR,
		DDL_DIRECTORY|DDL_ARCHIVE,
		(LPARAM)szPath );


void OnCommand( HWND hWnd, UINT nMsg,
		WPARAM wParam, LPARAM lParam )

	int nNotifyCode = HIWORD( wParam );
	int nEventID = LOWORD( wParam );
	switch( nEventID )
	
	case ID_ADD:
		OnAdd( hWnd );
		break;
	case ID_DEL:
		OnDel( hWnd );
		break;
	case ID_RESET:
		OnReset( hWnd );
		break;
	case ID_SEL:
		OnSelect( hWnd );
		break;
	case ID_FIND:
		OnFind( hWnd );
		break;
	case ID_PATH:
		OnPath( hWnd );
		break;
	case 1001:
		
			HWND hSimple   = GetDlgItem( hWnd, 1001 );
			HWND hDropDown = GetDlgItem( hWnd, 1002 );
			HWND hDropList = GetDlgItem( hWnd, 1003 );
			LRESULT nSel   = 0;
			switch( nNotifyCode )
			
			case CBN_SELCHANGE:
				nSel = SendMessage( hSimple, 
					CB_GETCURSEL, 0, 0 );
				SendMessage( hDropDown, 
					CB_SETCURSEL, nSel, 0 );
				SendMessage( hDropList, 
					CB_SETCURSEL, nSel, 0 );

				//MessageBox( NULL, "CBN_SELCHANGE",
				//	"WinCombo", MB_OK );

				break;
			
		
		break;
	


LRESULT CALLBACK WndProc( HWND   hWnd, 
						  UINT   nMsg,
						  WPARAM wParam,
						  LPARAM lParam )

	switch( nMsg )
	
	case WM_CREATE:
		OnCreate( hWnd, nMsg, wParam, lParam );
		break;
	case WM_COMMAND:
		OnCommand( hWnd, nMsg, wParam, lParam );
		break;
	case WM_DESTROY:
		PostQuitMessage( 0 );
		return 0;
	
	return DefWindowProc( hWnd, nMsg,
		wParam, lParam );


BOOL RegisterWnd( LPSTR pszClassName )

	WNDCLASSEX wce =  0 ;
	wce.cbSize        = sizeof( wce );
	wce.cbClsExtra    = 0;
	wce.cbWndExtra    = 0;
	wce.hbrBackground = HBRUSH(COLOR_BTNFACE+1);
	wce.hCursor       = NULL;
	wce.hIcon         = NULL;
	wce.hIconSm       = NULL;
	wce.hInstance     = g_hInst;
	wce.lpfnWndProc   = WndProc;
	wce.lpszClassName = pszClassName;
	wce.lpszMenuName  = NULL;
	wce.style         = CS_HREDRAW|CS_VREDRAW;

	ATOM nAtom = RegisterClassEx( &wce );
	if( 0 ==  nAtom )
	
		return FALSE;
	

	return TRUE;


HWND CreateWnd( LPSTR pszClassName )

	HMENU hMenu = LoadMenu( g_hInst,
		MAKEINTRESOURCE(IDR_MAIN) );
	HWND hWnd = CreateWindowEx( 0,
		pszClassName, "MyWnd", 
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, NULL, hMenu, g_hInst,
		NULL );
	return hWnd;


void DisplayWnd( HWND hWnd )

	ShowWindow( hWnd, SW_SHOW );
	UpdateWindow( hWnd );


void Message( )

	MSG msg =  0 ;
	while( GetMessage( &msg, NULL, 0, 0 ) )
	
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)

	g_hInst = hInstance;
	RegisterWnd( "MYWND" );
	HWND hWnd = CreateWnd( "MYWND" );
	DisplayWnd( hWnd );
	Message( );
	return 0;

列表框 ListBox

1 列表框的样式

  1.1 单选列表框 默认

  1.2 多选列表框 LBS_MULTIPLESEL

2 列表框的使用

  2.1 列表框的创建

窗口类名为LISTBOX, 使用CreateWindow/Ex

  2.2 增加选项

LB_ADDSTRING

LB_INSERTSTRING

  2.2 删除选项

LB_DELETESTRING 删除指定选项

LB_RESETCONTENT 清空所有选项

  2.3 选择项的获取和设置

LB_GETCURSEL 获取被选择项

LB_SETCURSEL 设置当前被选择项

LB_GETSEL  获取指定项的选择状态

LB_SETSEL  设置指定项的选择状态

LB_GETSELCOUNT 获取被选择的数量

LB_GETSELITEMS 获取被选择项的索引

2.4 查找 LB_FINDSTRING

2.5 获取指定项的文字

   LB_GETEXT  指定项的文字

   LB_GETTEXTLEN 指定项的文字的长度

   

2.6 选项的数据

   LB_SETITEMDATA 将自定义数据保存到

  指定的选项当中

   LB_GETITEMDATA 将自定义数据从指定

  选项中取出

2.7 目录信息

   LB_DIR 显示指定目录下的文件和子目录

  信息

2.8 通知消息

   LBN_SELCHANGE ListBox中的选择项发生

变化时,通知父窗口.

   注意:对于ListBox需要增加LBS_NOTIFY

样式,才能发送通知消息

// WinListBox.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"

HINSTANCE g_hInst   = NULL;
HWND      g_hSingle = NULL;
HWND      g_hMulti  = NULL;
void OnCreate( HWND hWnd, UINT nMsg, 
	WPARAM wParam, LPARAM lParam )

	g_hSingle = CreateWindow( 
		"LISTBOX", "SINGLE", 
		WS_CHILD|WS_VISIBLE|LBS_NOTIFY,
		50, 50, 200, 400, hWnd,
		(HMENU)1001, g_hInst, NULL );
	g_hMulti = CreateWindow( 
		"LISTBOX", "MULTI", 
		WS_CHILD|WS_VISIBLE|LBS_MULTIPLESEL|LBS_NOTIFY,
		300, 50, 200, 400, hWnd,
		(HMENU)1002, g_hInst, NULL );


void OnAdd( )

	CHAR szText[] = "ListBox 0";
	for( int nIndex=0; nIndex<10; nIndex++ )
		//添加项
		LRESULT nItem = 
			SendMessage( g_hSingle, LB_ADDSTRING,
			0, (LPARAM)szText );
		SendMessage( g_hMulti,  LB_ADDSTRING,
			0, (LPARAM)szText );
		szText[8]++;
	


void OnSelect( )
	//设置当前选择项
	SendMessage( g_hSingle, LB_SETCURSEL, 2, 0 );
	//设置指定项的选择状态
	for( int nIndex=0; nIndex<10; nIndex++ )
	
		SendMessage( g_hMulti, LB_SETSEL, 
			TRUE, nIndex );
	
	//获取所有选择项的数量
	LRESULT nCount = SendMessage( g_hMulti,
		LB_GETSELCOUNT, 0, 0 );
	if( nCount == 10 )
	
		MessageBox( NULL, "10", "10", MB_OK );
	
	//获取选择项的索引号
	INT nSel[20] =  0 ;
	SendMessage( g_hMulti, LB_GETSELITEMS,
		20, (LPARAM)nSel );


void OnCommand( HWND hWnd, UINT nMsg, 
	WPARAM wParam, LPARAM lParam )

	int nNotifyCode = HIWORD( wParam );
	int nCtrlID = LOWORD( wParam );
	switch( nCtrlID )
	
	case ID_ADD:
		OnAdd( );
		break;
	case ID_SELECT:
		OnSelect( );
		break;
	case 1001:
		
			switch( nNotifyCode )
			
			case LBN_SELCHANGE:
				MessageBox( NULL, "LBN_SELCHANGE",
					"ListBox", MB_OK );
				break;
			
		
		break;
	


LRESULT CALLBACK WndProc( HWND   hWnd, 
						  UINT   nMsg,
						  WPARAM wParam,
						  LPARAM lParam )

	switch( nMsg )
	
	case WM_CREATE:
		OnCreate( hWnd, nMsg, wParam, lParam );
		break;
	case WM_COMMAND:
		OnCommand( hWnd, nMsg, wParam, lParam );
		break;
	case WM_DESTROY:
		PostQuitMessage( 0 );
		return 0;
	
	return DefWindowProc( hWnd, nMsg,
		wParam, lParam );


BOOL RegisterWnd( LPSTR pszClassName )

	WNDCLASSEX wce =  0 ;
	wce.cbSize        = sizeof( wce );
	wce.cbClsExtra    = 0;
	wce.cbWndExtra    = 0;
	wce.hbrBackground = HBRUSH(COLOR_BTNFACE+1);
	wce.hCursor       = NULL;
	wce.hIcon         = NULL;
	wce.hIconSm       = NULL;
	wce.hInstance     = g_hInst;
	wce.lpfnWndProc   = WndProc;
	wce.lpszClassName = pszClassName;
	wce.lpszMenuName  = NULL;
	wce.style         = CS_HREDRAW|CS_VREDRAW;

	ATOM nAtom = RegisterClassEx( &wce );
	if( 0 ==  nAtom )
	
		return FALSE;
	

	return TRUE;


HWND CreateWnd( LPSTR pszClassName )

	HMENU hMenu = LoadMenu( g_hInst, 
		MAKEINTRESOURCE(IDR_MAIN) );
	HWND hWnd = CreateWindowEx( 0,
		pszClassName, "MyWnd", 
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, NULL, hMenu, g_hInst,
		NULL );
	return hWnd;


void DisplayWnd( HWND hWnd )

	ShowWindow( hWnd, SW_SHOW );
	UpdateWindow( hWnd );


void Message( )

	MSG msg =  0 ;
	while( GetMessage( &msg, NULL, 0, 0 ) )
	
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)

	g_hInst = hInstance;
	RegisterWnd( "MYWND" );
	HWND hWnd = CreateWnd( "MYWND" );
	DisplayWnd( hWnd );
	Message( );
	return 0;

滚动条

   1 滚动条样式

     1.1 水平滚动条 SBS_HORZ

     1.2 垂直滚动条 SBS_VERT

     

   2 滚动条的使用

2.1 滚动条的创建
        窗口类名称 SCROLLBAR 
     2.2 消息处理   
        2.2.1 水平滚动条 WM_HSCROLL
           LOWORD(wParam) - 滚动的标示
           HIWORD(wParam) - 当前滑块的位置
           lParam - 窗口的句柄
        2.2.2 垂直滚动条 WM_VSCROLL
           LOWORD(wParam) - 滚动的标示
           HIWORD(wParam) - 当前滑块的位置
           lParam - 窗口的句柄
        2.2.3 HIWORD(wParam)只在 
          SB_THUMBPOSITION/SB_THUMBTRACK时
          有效.
     2.3 滚动条的滚动范围
        SBM_SETRANGE 设置滚动条的滚动范围
           wParam - 最小值,起始值
           lParam - 最大值,终止值
        SBM_GETRANGE 获取滚动条的滚动范围
           wParam - 最小值得存放的INT的地址
           lParam - 最大值得存放的INT的地址
     2.4 滑块位置的设置和获取
        SBM_SETPOS 设置滑块位置
           wParam - 新的滑块位置
           lParam - 重新绘制窗口
        SBM_GETPOS 获取,返回当前位置
// WinScrollBar.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

HINSTANCE g_hInst = NULL;
HWND      g_hHorz = NULL;
HWND      g_hVert = NULL;
void OnCreate( HWND hWnd, WPARAM wParam,
	LPARAM lParam )
	//创建滚动条
	g_hHorz = CreateWindow( "SCROLLBAR", "HORZ",
		WS_CHILD|WS_VISIBLE|SBS_HORZ,
		0, 300, 300, 30, hWnd,
		(HMENU)1001, g_hInst, NULL );
	g_hVert = CreateWindow( "SCROLLBAR", "VERT",
		WS_CHILD|WS_VISIBLE|SBS_VERT,
		300, 0, 30, 300, hWnd,
		(HMENU)1002, g_hInst, NULL );
	//设置滚动范围
	SendMessage( g_hHorz, SBM_SETRANGE, 0, 300 );
	SendMessage( g_hVert, SBM_SETRANGE, 0, 300 );


void OnHScroll( HWND hWnd, WPARAM wParam,
	LPARAM lParam )

	int nScrollCode = LOWORD( wParam );
	int nPos        = HIWORD( wParam ); 
	switch( nScrollCode )
	
	case SB_LINELEFT: //左边箭头
		nPos = SendMessage( g_hHorz, SBM_GETPOS,
			0, 0 );
		nPos--;
		SendMessage( g_hHorz, SBM_SETPOS, 
			nPos, TRUE );
		break;
	case SB_LINERIGHT: //右边箭头
		nPos = SendMessage( g_hHorz, SBM_GETPOS,
			0, 0 );
		nPos++;
		SendMessage( g_hHorz, SBM_SETPOS, 
			nPos, TRUE );
		break;
	case SB_PAGELEFT: //滑块左边的空白区域
		nPos = SendMessage( g_hHorz, SBM_GETPOS,
			0, 0 );
		nPos -= 10;
		SendMessage( g_hHorz, SBM_SETPOS, 
			nPos, TRUE );
		break;
	case SB_PAGERIGHT://滑块右边的空白区域
		nPos = SendMessage( g_hHorz, SBM_GETPOS,
			0, 0 );
		nPos += 10;
		SendMessage( g_hHorz, SBM_SETPOS, 
			nPos, TRUE );
		break;
	case SB_THUMBPOSITION://拖拽滑块后
		SendMessage( g_hHorz, SBM_SETPOS,
			nPos, TRUE );
		break;
	

	InvalidateRect( hWnd, NULL, TRUE );


void OnVScroll( HWND hWnd, WPARAM wParam,
	LPARAM lParam )

	int nScrollCode = LOWORD( wParam );
	int nPos        = HIWORD( wParam ); 
	switch( nScrollCode )
	
	case SB_LINEUP: //上边箭头
		nPos = SendMessage( g_hVert, SBM_GETPOS,
			0, 0 );
		nPos--;
		SendMessage( g_hVert, SBM_SETPOS, 
			nPos, TRUE );
		break;
	case SB_LINEDOWN://下边箭头
		nPos = SendMessage( g_hVert, SBM_GETPOS,
			0, 0 );
		nPos++;
		SendMessage( g_hVert, SBM_SETPOS, 
			nPos, TRUE );
		break;
	case SB_PAGEUP://滑块上边的空白区域
		nPos = SendMessage( g_hVert, SBM_GETPOS,
			0, 0 );
		nPos -= 10;
		SendMessage( g_hVert, SBM_SETPOS, 
			nPos, TRUE );
		break;
	case SB_PAGEDOWN://滑块下边的空白区域
		nPos = SendMessage( g_hVert, SBM_GETPOS,
			0, 0 );
		nPos += 10;
		SendMessage( g_hVert, SBM_SETPOS, 
			nPos, TRUE );
		break;
	case SB_THUMBPOSITION://拖拽滑块后
		SendMessage( g_hVert, SBM_SETPOS,
			nPos, TRUE );
		break;
	

	InvalidateRect( hWnd, NULL, TRUE );
	

void OnPaint( HWND hWnd, WPARAM wParam,
	LPARAM lParam )

	PAINTSTRUCT ps =  0 ;
	HDC hDC = BeginPaint( hWnd, &ps );
	
	int nVert = SendMessage( g_hVert, 
		SBM_GETPOS, 0, 0 );
	int nHorz = SendMessage( g_hHorz, 
		SBM_GETPOS, 0, 0 );
	
	CHAR szText[] = "Hello ScroolBar";
	TextOut( hDC, 150 - nHorz, 150 - nVert, 
		szText, strlen(szText) );

	EndPaint( hWnd, &ps );


LRESULT CALLBACK WndProc( HWND   hWnd, 
						  UINT   nMsg,
						  WPARAM wParam,
						  LPARAM lParam )

	switch( nMsg )
	
	case WM_PAINT:
		OnPaint( hWnd, wParam, lParam );
		break;
	case WM_CREATE:
		OnCreate( hWnd, wParam, lParam );
		break;
	case WM_HSCROLL:
		OnHScroll( hWnd, wParam, lParam );
		break;
	case WM_VSCROLL:
		OnVScroll( hWnd, wParam, lParam );
		break;
	case WM_DESTROY:
		PostQuitMessage( 0 );
		return 0;
	
	return DefWindowProc( hWnd, nMsg,
		wParam, lParam );


BOOL RegisterWnd( LPSTR pszClassName )

	WNDCLASSEX wce =  0 ;
	wce.cbSize        = sizeof( wce );
	wce.cbClsExtra    = 0;
	wce.cbWndExtra    = 0;
	wce.hbrBackground = HBRUSH(COLOR_WINDOW);
	wce.hCursor       = NULL;
	wce.hIcon         = NULL;
	wce.hIconSm       = NULL;
	wce.hInstance     = g_hInst;
	wce.lpfnWndProc   = WndProc;
	wce.lpszClassName = pszClassName;
	wce.lpszMenuName  = NULL;
	wce.style         = CS_HREDRAW|CS_VREDRAW;

	ATOM nAtom = RegisterClassEx( &wce );
	if( 0 ==  nAtom )
	
		return FALSE;
	

	return TRUE;


HWND CreateWnd( LPSTR pszClassName )

	HWND hWnd = CreateWindowEx( 0,
		pszClassName, "MyWnd", 
		WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_HSCROLL|WS_VSCROLL,
		CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, NULL, NULL, g_hInst,
		NULL );
	return hWnd;


void DisplayWnd( HWND hWnd )

	ShowWindow( hWnd, SW_SHOW );
	UpdateWindow( hWnd );


void Message( )

	MSG msg =  0 ;
	while( GetMessage( &msg, NULL, 0, 0 ) )
	
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)

	g_hInst = hInstance;
	RegisterWnd( "MYWND" );
	HWND hWnd = CreateWnd( "MYWND" );
	DisplayWnd( hWnd );
	Message( );
	return 0;

控件的自绘制

 1 控件具有OWNERDRAW样式
    BUTTON LISTBOX COMBOBOX
  2 WM_MEASUREITEM
    计算控件的大小    
    (UINT) wParam - 控件ID
    (LPMEASUREITEMSTRUCT)lParam-控件项的大小
  3 WM_DRAWITEM
    实现控件的绘制
    (UINT) wParam - 控件ID
(LPDRAWITEMSTRUCT)lParam - 控件绘制的信息
// WinOwnerDraw.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

HINSTANCE g_hInst = NULL;

void OnCreate( HWND hWnd, WPARAM wParam, 
			  LPARAM lParam )

	CreateWindow( "BUTTON", "MyButton",
		WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,
		50, 50, 200, 50, hWnd,
		(HMENU)1001, g_hInst, NULL );


void OnDrawItem( HWND hWnd, WPARAM wParam, 
			  LPARAM lParam )

	LPDRAWITEMSTRUCT pDis = 
		( LPDRAWITEMSTRUCT )lParam;
	if( ODT_BUTTON == pDis->CtlType )
		//绘制按钮
		if( pDis->itemState & ODS_SELECTED )
		
			HBRUSH hBrush = CreateSolidBrush( 
				RGB(200, 200, 255 ) );
			HBRUSH hOldBrush = (HBRUSH)
				SelectObject( pDis->hDC, hBrush );
			RoundRect( pDis->hDC, pDis->rcItem.left,
			  pDis->rcItem.top, pDis->rcItem.right,
			  pDis->rcItem.bottom, 15, 15 );
			SelectObject( pDis->hDC, hOldBrush );
			DeleteObject( hBrush );
		
		else
		
			HBRUSH hBrush = CreateSolidBrush( 
				RGB(100, 100, 255 ) );
			HBRUSH hOldBrush = (HBRUSH)
				SelectObject( pDis->hDC, hBrush );
			RoundRect( pDis->hDC, pDis->rcItem.left,
			  pDis->rcItem.top, pDis->rcItem.right,
			  pDis->rcItem.bottom, 15, 15 );
			SelectObject( pDis->hDC, hOldBrush );
			DeleteObject( hBrush );
		
		//绘制按钮文字
		CHAR szName[260] =  0 ;
		GetWindowText( pDis->hwndItem, 
			szName, 260 );
		int nOldMode = SetBkMode( pDis->hDC, 
			TRANSPARENT );
		DrawText( pDis->hDC, szName, strlen(szName),
			&pDis->rcItem, 
			DT_CENTER|DT_VCENTER|DT_SINGLELINE );
		SetBkMode( pDis->hDC, nOldMode );
	


void OnMeasureItem( HWND hWnd, WPARAM wParam, 
			  LPARAM lParam )

	LPMEASUREITEMSTRUCT pMis =  
		(LPMEASUREITEMSTRUCT)lParam;
	pMis->itemHeight = 200;


LRESULT CALLBACK WndProc( HWND   hWnd, 
						  UINT   nMsg,
						  WPARAM wParam,
						  LPARAM lParam )

	switch( nMsg )
	
	case WM_CREATE:
		OnCreate( hWnd, wParam, lParam );
		break;
	case WM_DRAWITEM:
		OnDrawItem( hWnd, wParam, lParam );
		return 0;
	case WM_MEASUREITEM:
		OnMeasureItem( hWnd, wParam, lParam );
		return 0;
	case WM_DESTROY:
		PostQuitMessage( 0 );
		return 0;
	
	return DefWindowProc( hWnd, nMsg,
		wParam, lParam );


BOOL RegisterWnd( LPSTR pszClassName )

	WNDCLASSEX wce =  0 ;
	wce.cbSize        = sizeof( wce );
	wce.cbClsExtra    = 0;
	wce.cbWndExtra    = 0;
	wce.hbrBackground = HBRUSH(COLOR_WINDOW);
	wce.hCursor       = NULL;
	wce.hIcon         = NULL;
	wce.hIconSm       = NULL;
	wce.hInstance     = g_hInst;
	wce.lpfnWndProc   = WndProc;
	wce.lpszClassName = pszClassName;
	wce.lpszMenuName  = NULL;
	wce.style         = CS_HREDRAW|CS_VREDRAW;

	ATOM nAtom = RegisterClassEx( &wce );
	if( 0 ==  nAtom )
	
		return FALSE;
	

	return TRUE;


HWND CreateWnd( LPSTR pszClassName )

	HWND hWnd = CreateWindowEx( 0,
		pszClassName, "MyWnd", 
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, NULL, NULL, g_hInst,
		NULL );
	return hWnd;


void DisplayWnd( HWND hWnd )

	ShowWindow( hWnd, SW_SHOW );
	UpdateWindow( hWnd );


void Message( )

	MSG msg =  0 ;
	while( GetMessage( &msg, NULL, 0, 0 ) )
	
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)

	g_hInst = hInstance;
	RegisterWnd( "MYWND" );
	HWND hWnd = CreateWnd( "MYWND" );
	DisplayWnd( hWnd );
	Message( );
	return 0;






以上是关于win32day10-组合框/列表框/滚动条/控件的自绘制的主要内容,如果未能解决你的问题,请参考以下文章

Python中tkinter中控件的使用(6.Listbox列表框(添加滚动条))

在MFC中:静态文本类;按纽类;编辑框类;滚动条类;列表框类;组合框类等所对应的类名以及其功能

MFC编程入门之二十六(常用控件:滚动条控件ScrollBar)

VS2010-MFC(常用控件:滚动条控件Scroll Bar)

WIN32 API C 程序:尽管使用 CB_ADDSTRING 填充,组合框有一个空列表或不下拉

隐藏列表框滚动条和同步滚动