如何使位于无模式对话框上的列表框控件响应击键。 [英] How do I make a listbox control, located on a modeless dialog box, respond to key strokes.

查看:67
本文介绍了如何使位于无模式对话框上的列表框控件响应击键。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只想制作位于无模式对话框上的ListBox控件,以响应击键。例如:首先点击列表中的某个项目,然后按Delete键将其从列表中删除。



我发现一个空白对话框通过WM_KEYDOWN响应。但是当我在对话框上放置一个ListBox时。不处理相同的WM_KEYDOWN。然后我读到焦点设置为对话框上的控件。好。然后我遇到了WM_GETDLGCODE,我相信这是我解决问题的关键。但我无法弄明白。



我也会继续阅读。



- Scott



我尝试过的事情:



I would simply like to make a ListBox control, located on a Modeless dialog box, respond to key strokes. for example: one would first click on an item in the list and then press the Delete key to remove it from the list.

I have discovered that a blank dialog box responds via a WM_KEYDOWN. But when I place a ListBox on the dialog. The same WM_KEYDOWN is not processed. I then read that focus is set to a control on the dialog box. ok. I then come across WM_GETDLGCODE and I believe this my be the key to solving my problem. But I have not been able to figure it out.

I will keep reading too.

-Scott

What I have tried:

#include <windows.h>
#include <shobjidl.h>
#include <string>
#include <fstream>
#include <stdio.h>
#include "resource.h"
#include <sstream>

using namespace std;

// Dialog handle
HWND ghListDlg = 0;

// Combobox dialog window procedure
BOOL CALLBACK listDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	// Text buffer to be filled with string user entered into edit control
	wchar_t msgText[256] = L"";

	// Handles to the combo box controls
	static HWND hListBox = 0;
	static HWND hEditBox = 0;
	static HWND hAddButton = 0;

	int index = 0;

	switch (msg)
	{

	case WM_GETDLGCODE:
		MessageBox(0, L"WM_GETDLGCODE recieved", L"ListBox Message", MB_OK);
		return DLGC_WANTALLKEYS;

	case WM_ACTIVATE:
		if (0 == wParam)             // becoming inactive
		{
		}
		else                         // becoming active
		{
			ghListDlg = hDlg;
		}
		return true;

	case WM_INITDIALOG:
		// Controls are child windows to the dialog they lie on. In order to get and send information to and from a control
		// we will need a handle to it. So save a handle to the controls as the dialog is being initialized.
		// Recall that we get a handle to a child control on a dialog box with the GetDlgItem
		hListBox = GetDlgItem(hDlg, IDC_LISTBOX);
		hEditBox = GetDlgItem(hDlg, IDC_EDIT_MSG);
		hAddButton = GetDlgItem(hDlg, IDC_ADDBUTTON);

		return true;

	case WM_COMMAND:
		switch (HIWORD(wParam))
		{
			//User selected a combo box item
		case LBN_SELCHANGE:
			index = SendMessage(hListBox, LB_GETCURSEL, 0, 0);
			SendMessage(hListBox, LB_GETTEXT, (WPARAM)index, (LPARAM)msgText);
			MessageBox(0, msgText, L"ListBox Message", MB_OK);
			return true;
		}
		switch (LOWORD(wParam))
		{
			// User pressed the "Add" button
		case IDC_ADDBUTTON:
			// Get the text from the edit box
			GetWindowText(hEditBox, msgText, 256);

			// Add the text to the combo box only if the user entered a string greater than zero
			if (wcslen(msgText) > 0)
				SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)msgText);
			return true;
		}

		return true;

	case WM_CLOSE:
		DestroyWindow(hDlg);
		return true;

	case WM_DESTROY:
		PostQuitMessage(0);
		return true;

	}
	return false;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR cmdLine, int showCmd)
{
	// Create the modeless dialog window. This program is a pure dialog window application, and the
	//dialog window application, and the dialog window is the "main" window.

	// Create the modless dialog window
	ghListDlg = CreateDialog(
		hInstance, // Application instance
		MAKEINTRESOURCE(IDD_LISTDLG), // Dialog resource ID
		0, // Parent window--null for no parent
		listDlgProc); // Dialog window procedure

	// Show the list button dialog
	ShowWindow(ghListDlg, showCmd);

	// Enter the message loop
	MSG msg;
	ZeroMemory(&msg, sizeof(MSG));

	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (NULL == ghListDlg || !IsDialogMessage(ghListDlg, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int)msg.wParam;
}

推荐答案

您可以通过对控件本身进行子类化来完成此操作。通过这种方式,您可以访问它收到的WM_KEYUP消息,从而可以看到它何时收到VK_DELETE



首先,您定义一个函数作为窗口 - 对于控件的proc,接下来你是控件的子类。



当你显示一个显示项目的消息框时,你的代码会从控件中窃取焦点是值得的刚被选中。这意味着您单击一个项目,显示一个消息框,您关闭该框并点击删除,但没有任何反应。修复是(0)不显示消息框,(1)手动(即在代码中)在消息框被解除后将焦点设置回控件或(2)在您之前单击控件的空白部分点击删除按钮。



这是一个非常粗略的子类函数:



You can do this by sub-classing the control itself. This way, you get access to the WM_KEYUP messages it receives and thus, can see when it receives a VK_DELETE

First, you define a function to act as a window-proc for the control, next you subclass the control.

It's worth pointing out that your code steals focus from the control when you show a message-box displaying the item that was just selected. This means you click an item, a message-box is shown, you dismiss the box and hit delete, yet nothing happens. The fix is to either (0) Not show the message box, (1) manually (i.e in code) set the focus back to the control after the message box is dismissed or (2) click on an empty portion of the control before you hit the delete button.

Here's a very rough subclass function:

LRESULT CALLBACK myListBoxSubclassProc(HWND hWnd,
                                UINT uMsg,
                                WPARAM wParam,
                                LPARAM lParam,
                                UINT_PTR uIdSubclass,
                                DWORD_PTR dwRefData)
{
    switch (uMsg)
    {
        case WM_KEYUP:
            if (wParam == VK_DELETE)
            {
                int selectedIndex = SendMessage(hWnd, LB_GETCURSEL,0,0);
                SendMessage(hWnd, LB_DELETESTRING, selectedIndex, 0);
                MessageBeep(MB_OK);
            }
            break;
    }
    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}







以下是设置控件使用它的方法:






And here's how you set the control to use it:

case WM_INITDIALOG:
    // Controls are child windows to the dialog they lie on. In order to get and send information to and from a control
    // we will need a handle to it. So save a handle to the controls as the dialog is being initialized.
    // Recall that we get a handle to a child control on a dialog box with the GetDlgItem
    hListBox = GetDlgItem(hDlg, IDC_LISTBOX);
    hEditBox = GetDlgItem(hDlg, IDC_EDIT_MSG);
    hAddButton = GetDlgItem(hDlg, IDC_ADDBUTTON);

    SetWindowSubclass(hListBox, myListBoxSubclassProc, 0, 0);

    return true;







您需要包含< commctrl.h>并确保满足以下条件(包括之前)




You'll need to include <commctrl.h> and ensure that the following condition is met (before including it)

#if (_WIN32_WINNT >= 0x0501)


这篇关于如何使位于无模式对话框上的列表框控件响应击键。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆