win32没有鼠标,如何给按钮分配键盘快捷键?

问题描述 投票:0回答:1

我用纯C语言写了一个简单的win32图形用户界面应用程序,包括按钮和其他控件,没有MFC。我想让那些不能使用鼠标的人更容易使用它。

  1. 首先,我的示例代码不能响应 Tab 键将焦点从一个按钮移动到另一个按钮。我可以用鼠标按下UI按钮,然后它就会变成焦点,我可以使用 Space-bar但我不能使用以下方法将焦点移动到其他按钮上 TabShift+Tab. 如何解决这个问题?

  2. 我想给按钮分配键盘提示(小下划线),这样用户就可以使用键盘快捷键来激活按钮。

我有谷歌周围,但答案是很难谷歌,所以我需要有人指出我的一些文档。一个小的代码将是非常有用的。

下面是我的代码。我用WINE + TinyCC在Linux上编译和运行。


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

/* Yeres distributed forums node v0001 */

/* compile: wine tcc_win/tcc/tcc.exe win_yeres */


HWND status_text_hwnd = NULL;
HWND shutdown_hs_button_hwnd = NULL;

unsigned int button_height = 26;
unsigned int window_length = 400;
#define V_BUTTON_PADDING 2

int tor_running = 0;
int select_running = 0;


#include "yeres_bind.c"
#include "win_yeres_w1_proc.c"


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

  MSG msg;
  WNDCLASS wc;
  HWND hwnd;

  printf("\n  **  YERES v0001  **\n\n");


  // Fill in window class structure with parameters that describe
  // the main window.

  ZeroMemory(&wc, sizeof wc);
  wc.hInstance     = hInstance;
  wc.lpszClassName = "yeres_wcl";
  wc.lpfnWndProc   = (WNDPROC)w1_proc;
  wc.style         = CS_DBLCLKS|CS_VREDRAW|CS_HREDRAW;
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 0);
  wc.hIcon         = LoadIcon(NULL, IDI_EXCLAMATION);
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);

  if (FALSE == RegisterClass(&wc)) return 0;

  RECT client_rect;
  client_rect.left = 0;
  client_rect.top = 0;
  client_rect.right = window_length;
  client_rect.bottom = 500;

  /* calculate window size from known client area size */
  if (0 == AdjustWindowRect(&client_rect, wc.style, 0)) return 0;

  // create main window
  hwnd = CreateWindow(
    "yeres_wcl",
    "YERES control panel",
    WS_OVERLAPPEDWINDOW|WS_VISIBLE,
    30,
    30,
    client_rect.right,   //CW_USEDEFAULT
    client_rect.bottom,
    0,
    0,
    hInstance,
    0);

  if (NULL == hwnd) return 0;

  // Main message loop:
  while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return msg.wParam;
}

#define ID_TOR_CONTROL_PORT 1
#define ID_BIND 2
#define ID_UNBIND 3
#define ID_TOR_SHUTDOWN_HS 4
#define ID_PORT_NUM 5
#define ID_QUIT 6


LRESULT CALLBACK w1_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {

  int y = 4;
  int x;
  RECT rc;
  switch (message) {

    case WM_CREATE:

    ZeroMemory(&rc, sizeof(rc));
    GetClientRect(hwnd, &rc);
    if (rc.right) window_length = rc.right - rc.left;

    status_text_hwnd = CreateWindow("Static",
                "** YERES v0001 **\n\nPress 'Bind to localhost'..",
                WS_CHILD | WS_VISIBLE | SS_CENTER,
                3, y, window_length, (button_height * 3),
                hwnd, (HMENU) 1, NULL, NULL);
    y += button_height * 3;

    x = 2;
    CreateWindow("Static", "Port:",
                WS_CHILD | WS_VISIBLE | SS_CENTER,
                x, y, 60, button_height,
                hwnd, (HMENU) 1, NULL, NULL);
    x += 60;
    /* editable field here */
    CreateWindow("Edit", "19407", 
                WS_CHILD | WS_VISIBLE | WS_BORDER,
                x, y, 90, button_height, hwnd, (HMENU) ID_PORT_NUM,
                NULL, NULL);
    x += 120;

    CreateWindow("Button", "Bind to localhost",
                WS_VISIBLE | WS_CHILD ,
                x, y, 140, button_height,
                hwnd, (HMENU) ID_BIND, NULL, NULL);
    x += 140;
    CreateWindow("Button", "Unbind",
                WS_VISIBLE | WS_CHILD ,
                x, y, window_length - 2 - x, button_height,
                hwnd, (HMENU) ID_UNBIND, NULL, NULL);

    y += button_height + V_BUTTON_PADDING;

    CreateWindow("Button", "Use tor control port to start HiddenService",
                WS_VISIBLE | WS_CHILD ,
                2, y, window_length - 4, button_height,
                hwnd, (HMENU) ID_TOR_CONTROL_PORT, NULL, NULL);
    y += button_height + V_BUTTON_PADDING;

    shutdown_hs_button_hwnd = CreateWindow("Button", "Shutdown HiddenService",
                WS_VISIBLE | WS_CHILD ,
                2, y, window_length - 4, button_height,
                hwnd, (HMENU) ID_TOR_SHUTDOWN_HS, NULL, NULL);
    EnableWindow(shutdown_hs_button_hwnd, 0); /* inactive button */
    y += button_height + V_BUTTON_PADDING;

    CreateWindow("Button", "Shutdown EVERYTHING and QUIT",
                WS_VISIBLE | WS_CHILD ,
                2, y, window_length - 4, button_height,
                hwnd, (HMENU) ID_QUIT, NULL, NULL);
    y += button_height + V_BUTTON_PADDING;

    break;

    case WM_DESTROY:
    if (!tor_running && !select_running) PostQuitMessage(0);
    break;


    case WM_COMMAND:
    switch (LOWORD(wParam)) {
      case ID_BIND:
      yeres_bind();
      break;

      case ID_QUIT:
      PostQuitMessage(0);
      break;

      default: DefWindowProc(hwnd, message, wParam, lParam);
    }
    break;

    default:
    return DefWindowProc(hwnd, message, wParam, lParam);

  };
  return 0;
};

P.S. Sorry my bad English :)

c user-interface winapi wine
1个回答
0
投票

这很简单。在主消息处理循环中,我调用 IsDialogMessage() 适当 HWND. 然后,如果这个函数返回0,我就调用正常的TranslateMessage和DispatchMessage函数。下面是代码。

while(GetMessage(&msg, NULL, 0, 0) > 0) {
  if(!IsDialogMessage(hwnd, &msg)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  };

  yeres_select(); /* scan incoming connections on sockets using select(), activated by timer and/or other messages */

}

窗口中的每个按钮都有位 WS_TABSTOP 设置,所以当我按 Tab, IsDialogMessage() 会捕捉到信息并将焦点移到下一个按钮。可编辑也可以这样选择。

WS_GROUP 对我来说没有用。理论上它应该允许我使用方向键导航。我已经把 WS_GROUP 位在第一个按钮上。

CreateWindow("Button", "&Bind to localhost",
            WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_GROUP,
            x, y, 140, button_height,
            hwnd, (HMENU) ID_BIND, NULL, NULL);

安培符号即使在不使用 TranslateAccelerator() 调用,只需将其放入标签文本中 "&Bind to localhost"激活按钮,可以使用 Alt+B 左右。它是不区分大小写的。

我没有在Windows上检查它,但我想如果它在WINE中工作的话,应该是可以的。

© www.soinside.com 2019 - 2024. All rights reserved.