Что нового

Элементы GUI ComboBox, как узнать позиции начального и конечного символов выделенной строки через GUICtrlRecvMsg()

pvnn

Осваивающий
Сообщения
305
Репутация
32
Подсадите пожалуйста, как узнать позиции начального и конечного символов выделенной строки через GUICtrlRecvMsg() для ConboBox
Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ComboConstants.au3>
#include <Array.au3>

$hForm1 = GUICreate("Form1", 300, 200, -1, -1)
$Combo1 = GUICtrlCreateCombo("123456789", 8, 44, 150, 21, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
GUICtrlSetData(-1, "9876543|Testtext")
$ButPos = GUICtrlCreateButton("Get Select", 10, 80, 275, 25)

GUISetState()
    GUICtrlSetState($Combo1, $GUI_FOCUS)
    GUICtrlSendMsg($Combo1,$CB_SETEDITSEL,0,BitOR(BitShift(2,-16), BitAND(5,0xFFFF)))

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $ButPos
            ; $CB_GETEDITSEL (320)
             $aPos = GUICtrlRecvMsg($Combo1, $CB_GETEDITSEL)
            _ArrayDisplay($aPos)
    EndSwitch
WEnd
 

Norm

Продвинутый
Сообщения
289
Репутация
74
Вариатн с StringRegExp устроит?
Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ComboConstants.au3>
#include <Array.au3>

$hForm1 = GUICreate("Form1", 300, 200, -1, -1)
$Combo1 = GUICtrlCreateCombo("123456789", 8, 44, 150, 21, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
GUICtrlSetData(-1, "9876543|Testtext")
$ButPos = GUICtrlCreateButton("Get Select", 10, 80, 275, 25)

GUISetState()
GUICtrlSetState($Combo1, $GUI_FOCUS)
GUICtrlSendMsg($Combo1,$CB_SETEDITSEL,0,BitOR(BitShift(2,-16), BitAND(5,0xFFFF)))

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $ButPos
            Local $sComboString = GUICtrlRead($Combo1)
            Local $Pos = StringLen($sComboString)
            Local $aZh = StringRegExp($sComboString, "(^.|.$)", 3)
            If Not @error Then
                MsgBox(0,Default, "Cтрока -> "& $sComboString & @CRLF &"Первый -> "& $aZh[0] & @CRLF & _
                "Последний -> "& $aZh[1] & @CRLF &"Позиция последнего -> "& $Pos)
            EndIf
    EndSwitch
WEnd
 
Автор
P

pvnn

Осваивающий
Сообщения
305
Репутация
32

Norm

Нужно узнать позиции выделенного фрагмента текста, а не всего текста
Должно вернуть начало: 2, конец: 5, а у вас возвращает: 1, 9
 

Norm

Продвинутый
Сообщения
289
Репутация
74
У меня при запуске скрипта вся строка выделена.
Для элеменов Edit это можно без проблем определить с помошью библиотеки GuiEdit.au3
Функция _GUICtrlEdit_GetSel()
 
Последнее редактирование:
Автор
P

pvnn

Осваивающий
Сообщения
305
Репутация
32
Мне не нужно через UDF?, очень хотелось бы через GUICtrlRecvMsg(()
Странно, что у вас вся строка выделена, должна быть частично

Код:
GUICtrlSendMsg($Combo1,$CB_SETEDITSEL,0,BitOR(BitShift(2,-16), BitAND(5,0xFFFF)))
 

Norm

Продвинутый
Сообщения
289
Репутация
74
Посмотрите этот пример. Без UDF

Код:
_Main()

Func _Main()
    GUICreate("Получает позиции выделенного", 400, 296)
    Local $hCombo = GUICtrlCreateCombo("123456789", 10, 20, 350, 296, BitOR(0x2, 0x40)) ; BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
    GUICtrlSetData(-1, "9876543|Testtext")
    GUICtrlCreateLabel("Нажмите клавишу ENTER"& @CRLF &"При нажатии выделение в ComboBox уберается", 10, 45, 350, 20, 0x01) ; $SS_CENTER
    GUICtrlSetFont(-1, 11, 600)
    GUICtrlSetColor(-1, 0xFF0000)
    GUICtrlCreateLabel("При нажатии на кнопу происходит потеря фокуса и выделение текста на ComboBox", 10, 63, 350, 70, 0x01)
    GUICtrlSetFont(-1, 10, 600)
    Local $ButPos = GUICtrlCreateButton("Get Select", 10, 100, 350, 25, 0x0001) ; $BS_DEFPUSHBUTTON)
    Local $aPos, $iMemo = GUICtrlCreateEdit("", 10, 140, 350, 100, 0)
    GUICtrlSetFont($iMemo, 9, 400, 0, "Courier New")
    GUISetState()

    _GUICtrlComboBox_Set_EditSel($hCombo, 2, 7)  ; Выделяет символы в поле ввода

 While 1
        Switch GUIGetMsg()
            Case -3 ; $GUI_EVENT_CLOSE
                Exit
            Case $ButPos
                $aPos = _GUICtrlComboBox_Get_EditSel($hCombo)   ; Получает позиции выделенного
                If Not @error Then
                    GUICtrlSetData($iMemo, StringFormat("Позиции выделенного: %d - %d", $aPos[0], $aPos[1]) & @CRLF, 1)
                EndIf
        EndSwitch
    WEnd
    GUIDelete()
EndFunc   ;==>_Main

Func _GUICtrlComboBox_Set_EditSel($hWnd, $iStart, $iStop)
    If Not HWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
    Return _Send_Message($hWnd, 0x142, 0, _WinAPI_Make_Long($iStart, $iStop)) <> -1 ; 0x142 = $CB_SETEDITSEL
EndFunc   ;==>_GUICtrlComboBox_SetEditSel

Func _GUICtrlComboBox_Get_EditSel($hWnd)
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
    Local $tStart = DllStructCreate("dword Start")
    Local $tEnd = DllStructCreate("dword End")
    Local $iRet = _Send_Message($hWnd, 0x140, $tStart, $tEnd, 0, "struct*", "struct*") ; 0x140 = $CB_GETEDITSEL
    If $iRet = 0 Then Return SetError(-1, -1, -1)

    Local $aSel[2]
    $aSel[0] = DllStructGetData($tStart, "Start")
    $aSel[1] = DllStructGetData($tEnd, "End")
    Return $aSel
EndFunc   ;==>_GUICtrlComboBox_Get_EditSel

Func _Send_Message($hWnd, $iMsg, $wParam = 0, $lParam = 0, $iReturn = 0, $wParamType = "wparam", $lParamType = "lparam", $sReturnType = "lresult")
    Local $aCall = DllCall("user32.dll", $sReturnType, "SendMessageW", "hwnd", $hWnd, "uint", $iMsg, $wParamType, $wParam, $lParamType, $lParam)
    If @error Then Return SetError(@error, @extended, "")
    If $iReturn >= 0 And $iReturn <= 4 Then Return $aCall[$iReturn]
    Return $aCall
EndFunc   ;==>_Send_Message

Func _WinAPI_Make_Long($iLo, $iHi)
    Return BitOR(BitShift($iHi, -16), BitAND($iLo, 0xFFFF))
EndFunc   ;==>_WinAPI_Make_Long
 
Последнее редактирование:
Автор
P

pvnn

Осваивающий
Сообщения
305
Репутация
32
Обнаружил следующее...
Если вызвать функцию GUICtrlRecvMsg() или из UDF: _GUICtrlComboBox_GetEditSel(), до начала цикла опроса GUI While, то все работает.
А вот при нажатии на кнопку в форме, вызов того же самого - не работает.
Похоже это особенность работы ComboBox, т.е. когда я нажимаю на кнопку, фокус с Combo уходит и поэтому функции возвращают 0. Или это баг?

Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ComboConstants.au3>
#include <Array.au3>
#include <GuiComboBox.au3>

$hForm1 = GUICreate("Form1", 300, 200, -1, -1)
$Combo1 = GUICtrlCreateCombo("123456789", 8, 44, 150, 21)
GUICtrlSetData(-1, "9876543|Testtext")
$ButPos = GUICtrlCreateButton("Get Selected", 10, 80, 275, 25)

GUISetState()

GetSelected() ; Работает

While True
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $ButPos
            GetSelected() ; Не работает
    EndSwitch
WEnd

Func GetSelected()
    $aPos = GUICtrlRecvMsg($Combo1, $CB_GETEDITSEL)
    ConsoleWrite(@error&@CRLF)
    _ArrayDisplay($aPos)

    $aPos=_GUICtrlComboBox_GetEditSel($Combo1)
   ConsoleWrite(@error&@CRLF)
    _ArrayDisplay($aPos)
EndFunc
Сообщение автоматически объединено:

Пришлось отследить клик по ComboBox, чтобы решить.


Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ComboConstants.au3>
#include <Array.au3>
#include <GuiComboBox.au3>

Global $tInfo, $aPos
$hForm1 = GUICreate("Form1", 300, 200, -1, -1)
$Combo1 = GUICtrlCreateCombo("123456789", 8, 44, 150, 21)
GUICtrlSetData(-1, "9876543|Testtext")

$ButPos = GUICtrlCreateButton("Get Selected", 10, 80, 275, 25)
GUISetState()

$aPos = GUICtrlRecvMsg($Combo1, $CB_GETEDITSEL)

; Структура ComboBox
_GUICtrlComboBox_GetComboBoxInfo($Combo1, $tInfo)
$hComboEdit = DllStructGetData($tInfo, "hEdit")

While True
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        ; Клик по ComboBox
        Case $GUI_EVENT_PRIMARYUP
            If _WinAPI_GetFocus() = DllStructGetData($tInfo, "hEdit") Then
                $aPos = GUICtrlRecvMsg($Combo1, $CB_GETEDITSEL)
            EndIf

        Case $ButPos
            _ArrayDisplay($aPos)
    EndSwitch
WEnd
 
Последнее редактирование:

Norm

Продвинутый
Сообщения
289
Репутация
74
Эти проблемы я заметил и пример переделал.
Попробуйте его снова. Я там через нажатие клавиши ENTER сделал.
 
Автор
P

pvnn

Осваивающий
Сообщения
305
Репутация
32

Norm

Я хотел вот так. Решил через обработку сообщений в WM_COMMAND


Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ComboConstants.au3>
#include <Array.au3>
#include <GuiComboBox.au3>

Global $aPos
$hForm1 = GUICreate("Form1", 300, 200, -1, -1)
$Combo1 = GUICtrlCreateCombo("123456789", 8, 44, 150, 21)
$hCombo1=GUICtrlGetHandle($Combo1)
GUICtrlSetData(-1, "9876543|Testtext")
$ButPos = GUICtrlCreateButton("Get Selected", 10, 80, 275, 25)

GUIRegisterMsg( $WM_COMMAND, "WM_COMMAND" )
GUISetState()

While True
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit

        Case $ButPos
            MsgBox(64, 'Результат', ''& _
            'Начало выделения: '&$aPos[0]&@CRLF& _
            'Конец выделения: '&$aPos[1]&@CRLF& _
            'Позиция курсора: '&$aPos[1]&@CRLF&@CRLF& _
            '* Нумерация с нуля')
            ; После показа MsgBox возвращаем фокус и выделяем как было до MsgBox
            GUICtrlSetState($Combo1, $GUI_FOCUS)         ; Фокус на $Combo1, выделяется весь текст
            ; Выделяем как было до нажатия кнопки
            GUICtrlSendMsg($Combo1,$CB_SETEDITSEL,0,BitOR(BitShift($aPos[0],-16), BitAND($aPos[1],0xFFFF)))

    EndSwitch
WEnd

Func WM_COMMAND($hWnd, $iMsg, $wParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $hWndCombo
    $hWndFrom = $ilParam
    $iIDFrom = BitAND($wParam, 0xFFFF)    ; Low Word
    $iCode = BitShift($wParam, 16)        ; High Word

    Switch $hWndFrom
        Case $hCombo1
            ConsoleWrite($iCode&@CRLF)
            Switch $iCode
                Case $CBN_SELENDCANCEL
                    $aPos = GUICtrlRecvMsg($Combo1, $CB_GETEDITSEL)
                    If @error Then ; Если курсор в начале текста
                        Dim $aPos[2]
                        $aPos[0]=0
                        $aPos[1]=0
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc
 
Верх