Golden Blonde 发表于 2017-8-2 18:04:41

【VC】简易输入框(高仿山寨VB6的InputBox)

只有两个函数,全部源码不到150行。
**** Hidden Message *****怎么用?int main()
{
        PWCHAR ret = InputBox(NULL,L"tip",L"title",L"test",0,0);
        MessageBoxW(0,ret,0,0);
        if(ret){VirtualFree(ret,0,MEM_RELEASE);}
        return 0;
}

0xAA55 发表于 2017-8-3 09:18:15

如果是我的话我会在WM_CREATE里面创建控件。
另外不要在WndProc里面定义static变量或者访问全局变量,因为这样对多线程不友好。

Golden Blonde 发表于 2017-8-3 09:43:33

0xAA55 发表于 2017-8-3 09:18
如果是我的话我会在WM_CREATE里面创建控件。
另外不要在WndProc里面定义static变量或者访问全局变量,因为 ...

对的,这个InputBox是只支持单线程使用的。。。顺带问下,在WM_CREATE里创建控件有啥好处?

Ayala 发表于 2017-8-3 10:07:40

在消息循环里创建控件 方便InputBox模块化 方便移植 支持更多的属性

Golden Blonde 发表于 2017-8-3 10:11:48

Ayala 发表于 2017-8-3 10:07
在消息循环里创建控件 方便InputBox模块化 方便移植 支持更多的属性

学习了。谢谢。

0xAA55 发表于 2017-8-3 14:12:12

美俪女神 发表于 2017-8-3 09:43
对的,这个InputBox是只支持单线程使用的。。。顺带问下,在WM_CREATE里创建控件有啥好处? ...

从面向对象的角度来思考的话,WM_CREATE可以理解为你的窗口的构造函数。

涐吢铱舊囿儚 发表于 2017-8-31 12:32:40

学习一下。 :P

xf_lan 发表于 2017-9-25 08:07:33

66666666666666666666666

hxw 发表于 2019-12-6 12:49:03

来学习看看

系统消息 发表于 2019-12-7 00:51:57

我觉得最好像WinAPI那样外部定义CHAR或WCHAR数组,通过参数传缓冲区地址和长度给函数,InputBox函数内部又正好可以通过SendMessage发送EM_LIMITTEXT限制Edit控件的最大输入长度等于缓冲区大小(避免缓冲区越界访问),缓冲区数组可以设计成双向参数(初始显示缓冲区原来的旧文本,确定后把输入的新文本覆盖进去)。

imr2013 发表于 2022-11-23 22:43:00

学习一下

W741 发表于 2022-12-11 13:49:14

学习下:lol

tlwh163 发表于 2022-12-14 11:50:18

所以有最终形态的代码吗 想学习

xindaodan 发表于 2024-9-8 11:11:35

谢谢分享

tlwh163 发表于 2024-11-4 13:24:48

本帖最后由 tlwh163 于 2024-11-4 13:33 编辑

我认真学习了楼主的思想 然后自己查了些资料 也学着写了一个

是用 VisualFreeBasic 5.9.3 写的, 请指教!

''=========================================================================================
''高仿VB6输入框
''=========================================================================================
''      在对话框中显示提示,等待用户输入正文或按下按钮,并返回包含文本框内容的字符串表达式;
''      如果用户单击 确定 或 按下ENTER,则返回文本框中的内容(缓冲区长度260字符);
''      如果用户单击 取消 或 按下ESC,    则返回长度为零的字符串("");
''      -----------------------------------------------------------------------------------
''      InputBox(, Prompt[, Title] [, Default] [, xPos] [, yPos] [, HelpFile, Context])
''      InputBoxW() 需要辅助函数 InputBoxWndProcW() 协同工作
''      -----------------------------------------------------------------------------------
''      hParent:    可选的, 数值表达式,   指定对话框的拥有者窗体句柄(如果省略则把桌面窗体作为对话框拥有者)
''      Prompt:   必需的, 字符串表达式, 显示在对话框的消息标签中
''      Title:      可选的, 字符串表达式, 显示在对话框标题栏中(如果省略则把应用程序名放入标题栏)
''      Default:    可选的, 字符串表达式, 显示在文本框中,在没有其它输入时作为缺省值
''      xPos:       可选的, 数值表达式,   与yPos成对出现,指定对话框的水平位置(如果省略,则对话框会在水平方向居中)
''      yPos:       可选的, 数值表达式,   与xPos成对出现,指定对话框的垂直位置(如果省略,则对话框会在垂直方向居中)
''      Helpfile:   可选的, 字符串表达式, 识别帮助文件,用该文件为对话框提供上下文相关的帮助(必须同时提供Context)
''      Context:    可选的, 数值表达式,   由帮助文件的作者指定给某个帮助主题的帮助上下文编号(必须同时提供HelpFile)
''=========================================================================================

Function InputBoxWndProcW(ByVal hWnd As HWND, ByVal uMsg As UINT, ByVal wParam As WPARAM, ByVal lParam As LPARAM) As LResult
    Dim wResult As Any Ptr = 0
    Select Case uMsg
      Case WM_DESTROY
            RemovePropW(hWnd, "_ResultValue")
            PostQuitMessage(0)'使InputBox窗口的内部消息循环退出
      Case WM_KEYDOWN
            If wParam = VK_RETURN Then Return SendMessageW(hWnd, WM_COMMAND, IDOK, 0)
            If wParam = VK_ESCAPE Then Return SendMessageW(hWnd, WM_COMMAND, IDCANCEL, 0)
            If wParam = VK_F1   Then Return SendMessageW(hWnd, WM_COMMAND, 1808, 0)
      Case WM_COMMAND
            Select Case LoWord(wParam)
                Case IDOK       '确定: 返回 文本框内容
                  wResult = GetPropW(hWnd, "_ResultValue")
                  If wResult Then SendDlgItemMessageW(hWnd, 2000, WM_GETTEXT, 260, Cast(lParam, wResult))
                  SendMessageW(hWnd, WM_CLOSE, 0, 0)
                Case IDCANCEL   '取消: 什么也不做就可以了
                  SendMessageW(hWnd, WM_CLOSE, 0, 0)
                Case 1808       '帮助:
                  ''ToDo :
            End Select
    End Select
    Function = DefWindowProcW(hWnd, uMsg, wParam, lParam)
End Function

Function InputBoxW(hParent As hWnd = 0, Prompt As LPCWSTR, Title As LPCWSTR = 0, Default As LPCWSTR = 0, xPos As Long = 0, yPos As Long = 0, HelpFile As LPCWSTR = 0, Context As Integer = 0) As StringW
    ''InputBox函数返回值缓存区
    Dim dwBuff As WString * 260
    ''如果没有指定父窗体,将把桌面作为父窗体
    If hParent = NULL OrElse IsWindow(hParent) = 0 Then hParent = GetDesktopWindow()
    ''如果传入的是子窗体句柄,逆推得到该句柄的顶层父窗体
    While (GetWindowLongPtrW(hParent, GWL_STYLE) And WS_CHILD) = WS_CHILD
      hParent = GetParent(hParent)
    Wend
    ''创建输入对话框(Popup弹出式窗体)
    Dim HHIN As Hinstance = GetModuleHandleW(NULL)
    Dim hInputBox As hWnd = CreateWindowExW( _
      WS_EX_DLGMODALFRAME Or WS_EX_CONTROLPARENT, _ '对话框样式|允许TAB跳转
      "#32770", IIf(Title = 0, @(App.EXEName), Title), _
      WS_VISIBLE Or WS_CAPTION Or WS_POPUPWINDOW, _ '带标题栏的弹出窗口
      0, 0, 365, 155, hParent, 0, HHIN, 0 _
    )
    If hInputBox Then
      ''禁止拥有者窗体
      EnableWindow(hParent, False)
      ''把输入框数据的返回地址存入窗体属性
      SetPropW(hInputBox, "_ResultValue", Cast(HANDLE, @dwBuff))
      ''修改输入框样式
      Dim HHMenu As HMENU = GetSystemMenu(hInputBox, False)
      If HHMenu Then
            RemoveMenu(HHMenu, SC_MAXIMIZE, MF_BYCOMMAND)   '去掉系统菜单的最大化
            RemoveMenu(HHMenu, SC_MINIMIZE, MF_BYCOMMAND)   '去掉系统菜单的最小化
            RemoveMenu(HHMenu, SC_SIZE, MF_BYCOMMAND)       '去掉系统菜单的大小
            RemoveMenu(HHMenu, SC_RESTORE, MF_BYCOMMAND)    '去掉系统菜单的还原
      End If
      ''创建输入框子控件(标签+按钮+按钮+按钮+文本框)
      CreateWindowExW(0, "Static", NULL, WS_CHILD Or WS_VISIBLE, 5, 5, 275, 80, hInputBox, Cast(HMENU, 1000), HHIN, 0)
      CreateWindowExW(0, "Button", NULL, WS_CHILD Or WS_VISIBLE Or BS_DEFPUSHBUTTON, 285, 5, 65, 25, hInputBox, Cast(HMENU, IDOK), HHIN, 0)
      CreateWindowExW(0, "Button", NULL, WS_CHILD Or WS_VISIBLE, 285, 35, 65, 25, hInputBox, Cast(HMENU, IDCANCEL), HHIN, 0)
      CreateWindowExW(0, "Button", NULL, WS_CHILD, 285, 65, 65, 25, hInputBox, Cast(HMENU, 1808), HHIN, 0)'帮助按钮
      CreateWindowExW(WS_EX_CLIENTEDGE, "Edit", NULL, WS_BORDER Or WS_CHILD Or WS_VISIBLE Or ES_AUTOHSCROLL Or ES_AUTOVSCROLL, 5, 95, 350, 25, hInputBox, Cast(HMENU, 2000), HHIN, 0)
      ''设置统一的字体
      Dim As HGDIOBJ objFont = GetStockObject(DEFAULT_GUI_FONT)
      SendDlgItemMessageW(hInputBox, 1000, WM_SETFONT, Cast(wParam, objFont), 0)
      SendDlgItemMessageW(hInputBox, 1808, WM_SETFONT, Cast(wParam, objFont), 0)
      SendDlgItemMessageW(hInputBox, 2000, WM_SETFONT, Cast(wParam, objFont), 0)
      SendDlgItemMessageW(hInputBox, IDOK, WM_SETFONT, Cast(wParam, objFont), 0)
      SendDlgItemMessageW(hInputBox, IDCANCEL, WM_SETFONT, Cast(wParam, objFont), 0)
      ''设置子控件的文本
      Dim HH32 As Hinstance = GetModuleHandleW("user32.dll") : dwBuff = "&"
      If LoadStringW(HH32, 800, @dwBuff, 30) Then SendDlgItemMessageW(hInputBox, IDOK, WM_SETTEXT, 0, Cast(lParam, @dwBuff))
      If LoadStringW(HH32, 801, @dwBuff, 30) Then SendDlgItemMessageW(hInputBox, IDCANCEL, WM_SETTEXT, 0, Cast(lParam, @dwBuff))
      If LoadStringW(HH32, 808, @dwBuff, 30) Then SendDlgItemMessageW(hInputBox, 1808, WM_SETTEXT, 0, Cast(lParam, @dwBuff))
      dwBuff = 0
      If Prompt Then SendDlgItemMessageW(hInputBox, 1000, WM_SETTEXT, 0, Cast(lParam, Prompt))
      If Default Then SendDlgItemMessageW(hInputBox, 2000, WM_SETTEXT, 0, Cast(lParam, Default))
      ''显示输入框窗体
      ShowWindow(hInputBox, SW_SHOWNORMAL)
      UpdateWindow(hInputBox)
      ''计算输入框与拥有者父窗体的相对位置(根据xPos,yPos的指定值,如果未指定则父窗体居中)
      Dim As Rect mRc, Rc : GetWindowRect(hParent, @mRc) : GetWindowRect(hInputBox, @Rc)
      If xPos = 0 Then xPos = ((mRc.Right - mRc.Left) - (Rc.Right - Rc.Left)) / 2
      If yPos = 0 Then yPos = ((mRc.bottom - mRc.top) - (Rc.bottom - Rc.top)) / 2
      Rc.Left = mRc.Left + xPos : Rc.top = mRc.top + yPos
      MoveWindow(hInputBox, Rc.Left, Rc.top, Rc.Right, Rc.bottom, True)
      ''子类化输入框,并进入内部的消息循环,因为父窗体已经禁止了
      SetWindowLongPtrW(hInputBox, GWL_WNDPROC, Cast(LONG_PTR, @InputBoxWndProcW))
      Dim uMsg As MSG
      While GetMessageW(@uMsg, NULL, 0, 0)
            TranslateMessage(@uMsg)
            DispatchMessageW(@uMsg)
      Wend
      ''输入框关闭了,恢复父窗体
      EnableWindow(hParent, CTRUE)
      SetFocus(hParent)
    End If
    Function = dwBuff
End Function

gujin163 发表于 2024-11-5 10:59:37

给楼主点赞,希望继续分享!
页: [1]
查看完整版本: 【VC】简易输入框(高仿山寨VB6的InputBox)