I have problem with disable focus...
I get it when i try to disable forcus on single line edit control i am using
in my interpreter .
I try to set focus on main Window so..i think that edit control will lost focus but
nothing changed and edit control still have focus ..
so how kill focus on specific control?
One solution would be to SetFocus on another editbox or button. It won't work for the main window.
QuoteOne solution would be to SetFocus on another editbox or button. It won't work for the main window.
yes Charles it seems that i need to use button
becuse when carret is active on edit control
message_pump cannot receive keyboard event
and that kind a sucks
i even tried using child window with edit control but again same thing ...grrr
Have you tried using a button of zero size? :)
Zero size ???
well how then to click on that button?
general idea is to type text in edit control and then print that text on window
using GDI ...
but control cannot loose focus and keyboard event in that case not work
here is how is should look...
Charles..
i found one intersting on code project
but looks that is written in C#
https://www.codeproject.com/KB/GDI/557423/GdiTextRendererDemo.zip
Aurel,
I am not quite sure about your need.
If I understand correctly then have a look at the message pump in the following code.
Maybe IsDialogMessage() will resolve your keyboard event problem.
//KickResource "D:\Dev\Oxygen\o2\~code\~~~Resource.res"
//KickSwitch -run -64
//KickEnd
#autodim off
uses dialogs
%EditText 101
%ButtonEnter 201
%HWND_DESKTOP 0
%SPI_GETICONTITLELOGFONT 0x001F
%COLOR_BTNFACE 15
%BS_DEFAULT 0x0
type NONCLIENTMETRICS
long cbSize
long iBorderWidth
long iScrollWidth
long iScrollHeight
long iCaptionWidth
LOGFONT iCaptionHeight
long lfCaptionFont
long iSMCaptionWidth
LOGFONT iSMCaptionHeight
long lfSMCaptionFont
long iMenuWidth
LOGFONT iMenuHeight
LOGFONT lfMenuFont
LOGFONT lfStatusFont
LOGFONT fMessageFont
end type
'_____________________________________________________________________________
function WndProc(sys hWnd, wMsg, wParam, lparam) as sys callback
select case wMsg
case WM_COMMAND
word ctrlid = loword(wParam)
word event = hiword(wParam)
select case ctrlid
case EditText 'lparam is edit handle
if hiword(wParam) = EN_CHANGE //See also EN_UPDATE
long TextLen = 1 + SendMessageW(lparam, %WM_GETTEXTLENGTH, 0, 0)
wstring sText = nuls(TextLen) 'Build a buffer to receive text
GetWindowTextW(lparam, sText, TextLen)
sys hdc = GetDC(hWnd)
SetBkMode(hDC, TRANSPARENT)
InvalidateRect(hWnd, 0, 1) 'Erase the area
UpdateWindow(hWnd) 'Erase the area
TextOutW(hdc, 20, 30, sText, TextLen) 'Draw text
ReleaseDc(hdc) 'Clean up
endif
case ButtonEnter 'Button enter
if event = BN_CLICKED OR event = 1 then
beep(4500, 50)
endif
case IDOK 'Enter key
if event = BN_CLICKED OR event = 1 then
beep(5500, 50)
endif
case IDCANCEL 'Escape key
if event = BN_CLICKED OR event = 1 then
PostMessage(hwnd, WM_CLOSE, 0, 0) 'EndDialog(hWnd, 0)
endif
end select
case WM_DESTROY
PostQuitMessage(0)
return(0)
end select
return(DefWindowProc(hWnd, wMsg, wParam, lParam))
end function
'_____________________________________________________________________________
function WinMain()
NONCLIENTMETRICS NonClient
WndClass WindowClass
Msg TagMessage
sys hInstance, hwnd, hControl, hIcon
LONG WindowWidth, WindowHeight, WindowPosX, WindowPosY
WindowWidth = 250
WindowHeight = 170
WindowPosX = (GetSystemMetrics(SM_CXSCREEN) - WindowWidth) \ 2
WindowPosY = (GetSystemMetrics(SM_CYSCREEN) - WindowHeight) \ 2
NonClient.cbSize = SIZEOF(NONCLIENTMETRICS)
hIcon = ExtractIcon GETMODULEHANDLE(""), "Shell32.dll", 294 'o
hInstance = GetModuleHandle(0)
WindowClass.style = CS_HREDRAW | CS_VREDRAW
WindowClass.lpfnWndProc = @WndProc
WindowClass.cbClsExtra = 0
WindowClass.cbWndExtra = 0
WindowClass.hInstance = hInstance
WindowClass.hIcon = hIcon 'LoadIcon 0, IDI_APPLICATION
WindowClass.hCursor = LoadCursor(0, IDC_ARROW)
WindowClass.hbrBackground = COLOR_BTNFACE + 1
WindowClass.lpszMenuName = null
WindowClass.lpszClassName = strptr("OXYGEN BASIC")
RegisterClass(@WindowClass)
LOGFONT LogicalFont
SystemParametersInfo(SPI_GETICONTITLELOGFONT, SIZEOF(LOGFONT), @LogicalFont, 0)
sys hFont = CreateFontIndirect(@LogicalFont)
hwnd = CreateWindowEx(WS_EX_STATICEDGE, WindowClass.lpszClassName, "EditFocus " & sizeof(sys) * 8,
WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX | WS_CLIPSIBLINGS,
WindowPosX, WindowPosY, WindowWidth, WindowHeight, HWND_DESKTOP, 0, hInstance, 0)
hControl = CreateWindowEx(WS_EX_LEFT | WS_EX_STATICEDGE, 'Extended styles
"Edit", 'Class name
0, 'Caption
WS_CHILD | WS_VISIBLE | WS_TABSTOP | 'Window styles
ES_LEFT, 'Class styles
20, 100, 'Left, top
150, 20, 'Width, height
hWnd, EditText, 'Handle of parent, control ID
hInstance, NULL) 'Handle of instance, creation parameters
SendMessage(hControl, WM_SETFONT, hFont, true)
SetFocus(hControl)
hControl = CreateWindowEx(WS_EX_LEFT, 'Extended styles
"Button", 'Class name
"Enter", 'Caption
WS_CHILD | WS_VISIBLE | WS_TABSTOP | 'Window styles
BS_CENTER | BS_DEFAULT | BS_NOTIFY, 'Class styles
180, 100, 'Left, top
50, 20, 'Width, height
hWnd, ButtonEnter, 'Handle of parent, control ID
hInstance, NULL) 'Handle of instance, creation parameters
SendMessage(hControl, WM_SETFONT, hFont, true)
ShowWindow(hwnd, SW_SHOW)
UpdateWindow(hwnd)
sys RetVal
do until RetVal = -1 'Some error occured
RetVal = GetMessage(@TagMessage, 0, 0, 0)
if IsDialogMessage(hWnd, @TagMessage) = 0 'Zero if message has not been processed
TranslateMessage(@TagMessage)
DispatchMessage(@TagMessage)
endif
loop while RetVal 'If RetVal = 0 then WM_QUIT was received
DeleteObject(hFont)
DestroyIcon(hIcon)
end function
'_____________________________________________________________________________
WinMain()
end
'_____________________________________________________________________________
'
Hi Pierre
thanks,,,
but i am using Window ..not Dialog
What i am trying to do is :
when user type text in edit control ..and when want press ENTER key that text show on window
BUT edit control keep focus and disable keyboard event...only if you know trick and maybe is possible .
In Dialog we can use TAB key to swich between controls but on Window ..i don't know how
IsDialogMessage is a standard API, it can be used with either a dialog or a window, the code is the same to navigate between input fields with the TAB key.
More details there
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isdialogmessagea
ok Bernard
I read and what i figured is that work only with Dialogs
hmm i am confused with all this
you are not reading it correctly.
Read this again, the important words are "you can use it with any window that contains controls"
Although the IsDialogMessage function is intended for modeless dialog boxes, you can use it with any window that contains controls, enabling the windows to provide the same keyboard selection as is used in a dialog box.
@Zlatko, Have you asked ChatGPT about it?
You may get at least a starting Point. See ....
Here is my prompt.
##################
Act as a professional computer-programmer: Answer this question with Sample Code in PowerBasic:I have problem with disable focus...
I get it when i try to disable forcus on single line edit control i am using
in my interpreter .
I try to set focus on main Window so..i think that edit control will lost focus but
nothing changed and edit control still have focus ..
so how kill focus on specific control?
###################
QuoteTo disable focus on a single-line edit control in PowerBasic, you can use the SetFocus function with a parameter of 0. Here is some sample code that demonstrates this:
' Assume that hEdit is the handle to the single-line edit control
' and hMainWnd is the handle to the main window
' Disable focus on the edit control
SetFocus 0
' Set focus on the main window
SetFocus hMainWnd
This code first disables the focus on the edit control by calling SetFocus with a parameter of 0. This effectively removes the focus from the edit control and makes it available for other controls to receive focus. Then, the code sets the focus on the main window by calling SetFocus with the handle to the main window.
Note that this code assumes that you have already obtained the handles to the edit control and main window. If you haven't done so yet, you can use functions like GetDlgItem and GetActiveWindow to retrieve the handles.
Can it be done in another way also?QuoteYes, there are a few other ways to remove focus from a control in PowerBasic.
One way is to use the SetWindowLong function with the GWL_STYLE parameter to modify the window style of the control. You can remove the WS_TABSTOP style from the control to prevent it from receiving focus. Here's some sample code that demonstrates this:
' Assume that hEdit is the handle to the single-line edit control
' Remove the WS_TABSTOP style from the control
Dim dwStyle As Dword
dwStyle = GetWindowLong(hEdit, %GWL_STYLE)
dwStyle = dwStyle And Not %WS_TABSTOP
SetWindowLong hEdit, %GWL_STYLE, dwStyle
' Set focus on the main window
SetFocus hMainWnd
This code sends a WM_KILLFOCUS message to the control using SendMessage with the handle to the control and the message parameters set to 0. This causes the control to lose focus and update its appearance. Then, it sets the focus on the main window using SetFocus.
Please add a step-by-step explanation and a link to the API Description in MSDNQuoteSure, here's a step-by-step explanation of the two alternative methods I provided, along with links to the relevant API documentation on MSDN.
Method 1: Modifying the window style using SetWindowLong
Obtain the handle to the single-line edit control. This can be done using a function like GetDlgItem if the control is a child window of a dialog box, or by using FindWindowEx if the control is a top-level window.
Retrieve the current window style of the control using GetWindowLong with the GWL_STYLE parameter. The style value is a combination of bit flags that determine various aspects of the control's appearance and behavior.
Remove the WS_TABSTOP style from the style value by using a bitwise And operation with the complement of the WS_TABSTOP constant. The WS_TABSTOP style specifies that the control can receive input focus by pressing the Tab key.
Set the modified style value using SetWindowLong with the GWL_STYLE parameter. This updates the window style of the control and removes its ability to receive focus.
Set focus on the desired window or control using SetFocus.
Here's some sample code that demonstrates this method:
' Assume that hEdit is the handle to the single-line edit control
' Remove the WS_TABSTOP style from the control
Dim dwStyle As Dword
dwStyle = GetWindowLong(hEdit, %GWL_STYLE)
dwStyle = dwStyle And Not %WS_TABSTOP
SetWindowLong hEdit, %GWL_STYLE, dwStyle
' Set focus on the main window
SetFocus hMainWnd
You can find more information about the GetWindowLong and SetWindowLong functions on the following pages of the MSDN documentation:
GetWindowLong function: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlonga
SetWindowLong function: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlonga
Method 2: Sending a WM_KILLFOCUS message using SendMessage
Obtain the handle to the single-line edit control as described in method 1.
Send a WM_KILLFOCUS message to the control using SendMessage with the handle to the control and the message parameters set to 0. This message notifies the control that it has lost focus and causes it to update its appearance accordingly.
Set focus on the desired window or control using SetFocus.
Here's some sample code that demonstrates this method:
' Assume that hEdit is the handle to the single-line edit control
' Send a WM_KILLFOCUS message to the control
SendMessage hEdit, %WM_KILLFOCUS, 0, 0
' Set focus on the main window
SetFocus hMainWnd
You can find more information about the SendMessage function and the WM_KILLFOCUS message on the following pages of the MSDN documentation:
SendMessage function: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
WM_KILLFOCUS message: https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-killfocus
Any further Comments?
Just for fun i have also aske "BING" about the same.
QuoteHello, I'm a professional computer-programmer and I can try to help you with your question. To disable focus on a single line edit control in PowerBasic, you can use the %EM_KILLFOCUS message. This message tells the edit control to lose the keyboard focus and hide the caret. You can send this message to the edit control using the CONTROL SEND statement. For example:
Code:
CONTROL SEND hDlg, %ID_EDIT, %EM_KILLFOCUS, 0, 0
This will remove the focus from the edit control with the ID %ID_EDIT in the dialog hDlg. You can also use the CONTROL SET FOCUS statement to set the focus to another control in the dialog, such as the main window. For example:
Code:
CONTROL SET FOCUS hDlg, %ID_MAIN
This will set the focus to the control with the ID %ID_MAIN in the dialog hDlg. I hope this helps you with your problem. If you have any further questions, please let me know.
While this is not really useful, the BING even tries to use PowerBasic native Commands :-).
'Oh, I see. You want an example that shows how to disable focus on a single line edit control using WinAPI and 'PowerBasic. Well, in that case, you can use the code snippet below:
Code:
#COMPILE EXE
#DIM ALL
#INCLUDE "win32api.inc"
%IDC_EDIT = 100
%IDC_BUTTON = 101
CALLBACK FUNCTION DlgProc
SELECT CASE CBMSG
CASE %WM_COMMAND
IF CBCTL = %IDC_BUTTON THEN
' Send the %EM_KILLFOCUS message to the edit control
CONTROL SEND CBHNDL, %IDC_EDIT, %EM_KILLFOCUS, 0, 0
' Set the focus to the button control
CONTROL SET FOCUS CBHNDL, %IDC_BUTTON
END IF
CASE %WM_CLOSE
DIALOG END CBHNDL
END SELECT
END FUNCTION
FUNCTION PBMAIN()
LOCAL hDlg AS DWORD
DIALOG NEW 0, "WinAPI Example", , , 200, 100, %WS_CAPTION OR %WS_SYSMENU TO hDlg
CONTROL ADD TEXTBOX, hDlg, %IDC_EDIT, "Some text", 10, 10, 180, 20
CONTROL ADD BUTTON, hDlg, %IDC_BUTTON, "Disable Focus", 50, 40, 100, 20
DIALOG SHOW MODAL hDlg CALL DlgProc
END FUNCTION
This code creates a dialog box with a single line edit control and a button. When the button is clicked, it sends the %EM_KILLFOCUS message to the edit control using the CONTROL SEND statement. This tells the edit control to lose the keyboard focus and hide the caret. Then it sets the focus to the button control using the CONTROL SET FOCUS statement. This way, the edit control does not have focus anymore.
There may be other ways to disable focus on a single line edit control using WinAPI and PowerBasic, but the one I showed you is the simplest and most straightforward one. Another possible way is to subclass the edit control and handle the %WM_SETFOCUS message yourself. You can use the SetWindowLong function to replace the edit control's window procedure with your own function. Then you can decide what to do when the edit control receives the %WM_SETFOCUS message. For example, you can ignore it or pass it to another control. However, this method is more complicated and requires more coding. You also need to be careful not to break the normal functionality of the edit control. Therefore, I would recommend using the %EM_KILLFOCUS message instead.
OK, I can show you a sample code for subclassing the edit control. Please note that this is not the recommended way to disable focus on the edit control, and it may have some side effects. Use it at your own risk.
#COMPILE EXE
#DIM ALL
#INCLUDE "win32api.inc"
%IDC_EDIT = 100
%IDC_BUTTON = 101
GLOBAL OldProc AS LONG ' The original window procedure of the edit control
CALLBACK FUNCTION DlgProc
SELECT CASE CBMSG
CASE %WM_COMMAND
IF CBCTL = %IDC_BUTTON THEN
' Set the focus to the button control
CONTROL SET FOCUS CBHNDL, %IDC_BUTTON
END IF
CASE %WM_CLOSE
DIALOG END CBHNDL
END SELECT
END FUNCTION
FUNCTION EditProc(BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, _
BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
' This is the new window procedure for the edit control
SELECT CASE wMsg
CASE %WM_SETFOCUS ' When the edit control receives the focus message
' Ignore it and return zero
FUNCTION = 0
EXIT FUNCTION
END SELECT
' For other messages, call the original window procedure
FUNCTION = CallWindowProc(OldProc, hWnd, wMsg, wParam, lParam)
END FUNCTION
FUNCTION PBMAIN()
LOCAL hDlg AS DWORD
LOCAL hEdit AS DWORD ' The handle of the edit control
DIALOG NEW 0, "WinAPI Example", , , 200, 100, %WS_CAPTION OR %WS_SYSMENU TO hDlg
CONTROL ADD TEXTBOX, hDlg, %IDC_EDIT, "Some text", 10, 10, 180, 20
CONTROL ADD BUTTON, hDlg, %IDC_BUTTON, "Disable Focus", 50, 40, 100, 20
CONTROL HANDLE hDlg, %IDC_EDIT TO hEdit ' Get the handle of the edit control
OldProc = SetWindowLong(hEdit, %GWL_WNDPROC, CODEPTR(EditProc)) ' Subclass the edit control
DIALOG SHOW MODAL hDlg CALL DlgProc
END FUNCTION
This code subclasses the edit control using the SetWindowLong function and replaces its window procedure with a custom function called EditProc. The EditProc function ignores the %WM_SETFOCUS message and returns zero. This prevents the edit control from getting focus and showing the caret. The original window procedure is stored in a global variable called OldProc and is called for other messages. I hope this sample code helps you understand how to subclass the edit control. If you have any further questions, please let me know.
Aurel,
As Bernard said, IsDialogMessage() can be used with window, GetDlgItem() also.
SendDlgItemMessage() work, but I didn't find any mention for window compatibility, so i'd use it with care.
For the edit control focus, I'm not completely sure of what you wanted,
I think that we both agree that an edit control with no focus won't get any character.
Here is a variant of my previous code that may do what you want...
//KickResource "D:\Dev\Oxygen\o2\~code\~~~Resource.res"
//KickSwitch -run -64
//KickEnd
#autodim off
uses dialogs
%EditText 101
%ButtonEnter 201
%HWND_DESKTOP 0
%SPI_GETICONTITLELOGFONT 0x001F
%COLOR_BTNFACE 15
%BS_DEFAULT 0x0
type NONCLIENTMETRICS
long cbSize
long iBorderWidth
long iScrollWidth
long iScrollHeight
long iCaptionWidth
LOGFONT iCaptionHeight
long lfCaptionFont
long iSMCaptionWidth
LOGFONT iSMCaptionHeight
long lfSMCaptionFont
long iMenuWidth
LOGFONT iMenuHeight
LOGFONT lfMenuFont
LOGFONT lfStatusFont
LOGFONT fMessageFont
end type
'_____________________________________________________________________________
function WndProc(sys hWnd, wMsg, wParam, lparam) as sys callback
select case wMsg
case WM_COMMAND
word ctrlid = loword(wParam)
word event = hiword(wParam)
select case ctrlid
case ButtonEnter, IDOK 'Button [Enter] or the Enter key
if event = BN_CLICKED OR event = 1 then
sys hEditBot = GetDlgItem(hWnd, EditText) 'Get edit handle
long TextLen = 1 + SendMessageW(hEditBot, %WM_GETTEXTLENGTH, 0, 0) 'Get text lenght
wstring sText = nuls(TextLen) 'Build a buffer to store text
GetWindowTextW(hEditBot, sText, TextLen) 'Copy the text to the sText buffer
sys hdc = GetDC(hWnd) 'Get device context
SetBkMode(hDC, TRANSPARENT) 'Transparent background
InvalidateRect(hWnd, 0, 1) 'Erase previous text
UpdateWindow(hWnd) 'Erase previous text
TextOutW(hdc, 20, 30, sText, TextLen) 'Draw text
ReleaseDc(hdc) 'Clean up
endif
case IDCANCEL 'Escape key
if event = BN_CLICKED OR event = 1 then
PostMessage(hwnd, WM_CLOSE, 0, 0)
endif
case EditText
'if hiword(wParam) = EN_CHANGE // See also EN_UPDATE
'endif
end select
case WM_DESTROY
PostQuitMessage(0)
return(0)
end select
return(DefWindowProc(hWnd, wMsg, wParam, lParam))
end function
'_____________________________________________________________________________
function WinMain()
NONCLIENTMETRICS NonClient
WndClass WindowClass
Msg TagMessage
sys inst, hwnd, hControl, hIcon, inst
sys WindowWidth, WindowHeight, WindowPosX, WindowPosY
WindowWidth = 250
WindowHeight = 170
WindowPosX = (GetSystemMetrics(SM_CXSCREEN) - WindowWidth) \ 2
WindowPosY = (GetSystemMetrics(SM_CYSCREEN) - WindowHeight) \ 2
NonClient.cbSize = SIZEOF(NONCLIENTMETRICS)
hIcon = ExtractIcon GETMODULEHANDLE(""), "Shell32.dll", 294 'o
inst = GetModuleHandle(0)
WindowClass.style = CS_HREDRAW | CS_VREDRAW
WindowClass.lpfnWndProc = @WndProc
WindowClass.cbClsExtra = 0
WindowClass.cbWndExtra = 0
WindowClass.hInstance = inst
WindowClass.hIcon = hIcon 'LoadIcon(0, IDI_APPLICATION) can be used
WindowClass.hCursor = LoadCursor(0, IDC_ARROW)
WindowClass.hbrBackground = COLOR_BTNFACE + 1
WindowClass.lpszMenuName = null
WindowClass.lpszClassName = strptr("OXYGEN BASIC")
RegisterClass(@WindowClass)
LOGFONT LogicalFont
SystemParametersInfo(SPI_GETICONTITLELOGFONT, SIZEOF(LOGFONT), @LogicalFont, 0)
sys hFont = CreateFontIndirect(@LogicalFont)
hwnd = CreateWindowEx(WS_EX_STATICEDGE, WindowClass.lpszClassName, "EditFocus " & sizeof(sys) * 8,
WS_OVERLAPPED | WS_BORDER | WS_DLGFRAME | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX | WS_CLIPSIBLINGS,
WindowPosX, WindowPosY, WindowWidth, WindowHeight, HWND_DESKTOP, 0, inst, 0)
hControl = CreateWindowEx(WS_EX_LEFT | WS_EX_STATICEDGE, 'Extended styles
"Edit", 'Class name
0, 'Caption
WS_CHILD | WS_VISIBLE | WS_TABSTOP | 'Window styles
ES_LEFT, 'Class styles
20, 100, 'Left, top
150, 20, 'Width, height
hWnd, EditText, 'Handle of parent, control ID
inst, NULL) 'Handle of instance, creation parameters
SendMessage(hControl, WM_SETFONT, hFont, true)
SetFocus(hControl)
hControl = CreateWindowEx(WS_EX_LEFT, 'Extended styles
"Button", 'Class name
"Enter", 'Caption
WS_CHILD | WS_VISIBLE | WS_TABSTOP | 'Window styles
BS_CENTER | BS_DEFAULT | BS_NOTIFY, 'Class styles
180, 100, 'Left, top
50, 20, 'Width, height
hWnd, ButtonEnter, 'Handle of parent, control ID
inst, NULL) 'Handle of instance, creation parameters
SendMessage(hControl, WM_SETFONT, hFont, true)
ShowWindow(hwnd, SW_SHOW)
UpdateWindow(hwnd)
sys RetVal
do until RetVal = -1 'Some error occured
RetVal = GetMessage(@TagMessage, 0, 0, 0)
if IsDialogMessage(hWnd, @TagMessage) = 0 'Zero if message has not been processed
TranslateMessage(@TagMessage)
DispatchMessage(@TagMessage)
endif
loop while RetVal 'If RetVal = 0 then WM_QUIT was received
DeleteObject(hFont)
DestroyIcon(hIcon)
end function
'_____________________________________________________________________________
WinMain()
end
'_____________________________________________________________________________
'
Pierre
it is simple what i want :
after i type text in edit control and when i press ENTER key i want that edit control lost focus
BUT when I do that , carret is still in edit control and disable WM_KEYDOWN event ..message
i hope that you guys understand it now...yes looks simple but is not and not work...
I can try IsDialogMessage that is not problem.
Also thanks Theo
that is very interesting ..but i already try many options
i will chaecki t again
Ok,
What if after ReleaseDc(hdc) you add SetFocus(hWnd) ?
Pierre
ReleaseDC and SetFocus don't have nothing in common
I will post you this simple testing program so anyone can try:
'unfocus control
$ filename "GUI038.exe"
% WM_NCACTIVATE = 0x0086
' new awinh037
include "rtl32.inc" : include "awinh037.inc" : #lookahead
'globals
INT win,x=0,y=0,w=600,h=430,wstyle = WS_MINMAXSIZE
INT inbox
INT butt, b0ID = 100
INT edit1, editID1 = 101
INT edit2, editID2 = 102
' open window with message loop...
win = SetWindow("GUI_App awinh037",x,y,w,h,0,wstyle)
butt = SetButton(win ,420,320,80,26,"ENTER",0x50001000 | WS_TABSTOP,0x200,b0ID)
edit1 = SetEditBox(win,20,320,380,22,"Enter text...",0x50800000 | WS_TABSTOP | ES_WANTRETURN,0x200,editID1)
'child window
'inbox = SetWindow("Inbox",10,300,230,80, win ,wstyle )
'add edit on child window
'edit2 = SetEditBox(inbox,10,10,150,23,"",0x50800000 | WS_TABSTOP | ES_WANTRETURN,0x200,editID2)
'setfocus inbox
Wait() '/// message loop ///
Function WndProc(sys hwnd,wmsg,wparam,lparam) as sys callback
win = hwnd 'assign WIN with HWND
SELECT hwnd
CASE win
Select wmsg
case wm_create
'button0 = SetButton(win,10,40,80,26,"Close (X)",0x50001000,0x200,b0ID)
case wm_keydown
'SetFocus butt
if wParam = 13
print "VK_ENTER"
' SetFocus butt
'SendMessage WM_KILLFOCUS,edit1,0
end if
/*
CASE WM_NCACTIVATE
STATIC hWndSaveFocus AS DWORD
IF WPARAM = 0
' Save control focus
hWndSaveFocus = GetFocus()
ELSEIF hWndSaveFocus
' Restore control focus
SetFocus(hWndSaveFocus)
hWndSaveFocus = 0
END IF */
CASE WM_CLOSE
CloseWindow(win)
EndProgram
End Select
END SELECT
RETURN Default
END FUNCTION
Once you press the enter key, you can put the focus on another control (even a hidden control).
Or you can use something like this, to simulate a mouse click on another control.
void PutFocusOn(IN HWND nObjectHandle, IN LPARAM lParam = 0) {
PostMessage(nObjectHandle, WM_LBUTTONDOWN, 0, lParam);
PostMessage(nObjectHandle, WM_LBUTTONUP, 0, lParam);
}
Hi Bernard,Pierre...all
I understand what you say ...and i even can add hidden control in my interpreter
that is not problem , but would be better to set focus back to window..
In Pierre program ..main trick is with IDOK and have exactly what i want .
So i must test this first ..
thanks guys !!!
Oh what a snap
Not work work without IsDialogMesage
After try/error/not work ... things
it looks that work using IsDialogMessage(hwnd,msg)
I am not sure if i can add it into interpreter
but looks that work as native app ,ok looks like this :
and i hope that some of you try and find it useful ;)
'unfocus control
$ filename "GUI038.exe"
% WM_NCACTIVATE = 0x0086
' new awinh037
include "rtl32.inc" : include "awinh037.inc" : #lookahead
Declare Function IsDialogMessage Lib "user32.dll" Alias "IsDialogMessageA" (ByVal hDlg As Long, lpMsg As MSG) As Long
'globals
INT win,x=0,y=0,w=600,h=430,wstyle = WS_MINMAXSIZE
INT inbox
INT butt
INT edit1, editID1 = 101
INT edit2, editID2 = 102
% b0ID = 100
' open window...
win = SetWindow("GUI_App awinh037",x,y,w,h,0,wstyle)
butt = SetButton(win ,420,320,80,26,"ENTER",0x50001000 | WS_TABSTOP ,0x200,b0ID)
edit1 = SetEditBox(win,20,320,380,22,"Enter text...",0x50800000| WS_TABSTOP ,0x200,editID1)
'/// message loop ///
WHILE GetMessage (wm,0,0,0)<>0
if IsDialogMessage(win,wm)=0
TranslateMessage wm
DispatchMessage wm
end if
WEND
Function WndProc(sys hwnd,wmsg,wparam,lparam) as sys callback
win = hwnd 'assign WIN with HWND
SELECT hwnd
CASE win
Select wmsg
case wm_create
'button0 = SetButton(win,10,40,80,26,"Close (X)",0x50001000,0x200,b0ID)
CASE WM_KEYDOWN
'SetFocus butt
if wParam = 13
print "VK_ENTER"
'InvalidateRect(edit1, 0, 1)
end if
CASE WM_LBUTTONDOWN
InvalidateRect(win, 0, 1)
'print "invalid"
CASE WM_COMMAND
controlID = LoWord(wParam) 'get control ID
notifyCode = HiWord(wParam) 'get notification message
select controlID
case b0ID
if notifycode = BN_CLICKED OR notifycode = 1
print "ENTER PRES!"
end if
case IDOK
if notifycode = 0
'print "IDOK-1"
'InvalidateRect(edit1, 0, -1)
SendMessage edit1,WM_SETTEXT,0,""
end if
case IDCANCEL
print "ESCAPE"
end select
CASE WM_CLOSE
CloseWindow(win)
EndProgram
End Select
END SELECT
RETURN Default
END FUNCTION
QuotePierre, ReleaseDC and SetFocus don't have nothing in common...
Aurel, I never said it have.
ReleaseDc(hdc) is there to take care of sys hdc = GetDC(hWnd).
OK Pierre i get it ..
but in overall it is not anything connected with HDC
i have probem with IDOK . so IDOK message not work if IsDialogMessage is not added into message loop
Please if you have time check next program , in order to work add include file awinh037.inc
and tell me how work ?
seems all work fine ..only strange problem i have with CRLF which NOT execute after text then i need to add it to buffer
before text ???
that looks crazy :
'unfocus control
$ filename "GUI038.exe"
% WM_NCACTIVATE = 0x0086
' new awinh037
include "rtl32.inc" : include "awinh037.inc" : #lookahead
Declare Function IsDialogMessage Lib "user32.dll" Alias "IsDialogMessageA" (ByVal hDlg As Long, lpMsg As MSG) As Long
'globals
INT win,x=0,y=0,w=600,h=430,wstyle = WS_MINMAXSIZE
INT inbox
INT butt, b0ID = 100
INT edit1, editID1 = 101
INT edit2, editID2 = 102
string CRLF = chr(13)+chr(10)
string txbuff = space(256)
char buff[4096]
' open window...
win = SetWindow("GUI_App awinh037",x,y,w,h,0,wstyle)
butt = SetButton(win ,420,320,80,26,"ENTER",0x50001000 | WS_TABSTOP ,0x200,b0ID)
'single line edit control
edit1 = SetEditBox(win,20,320,380,23,"Enter text...",0x50800000| WS_TABSTOP ,0x200,editID1)
ControlFont(edit1, 17,7, 100, "Courier New")
'multi line edit control
edit2 = SetEditBox(win,20,40,400,200,"",WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL|WS_HSCROLL|ES_AUTOVSCROLL,0x200,editID2)
ControlFont(edit2, 16,8, 100, "Consolas")
'/// message loop ///
WHILE GetMessage (wm,0,0,0)<>0
if IsDialogMessage(win,wm)=0
TranslateMessage wm
DispatchMessage wm
end if
WEND
Function WndProc(sys hwnd,wmsg,wparam,lparam) as sys callback
win = hwnd 'assign WIN with HWND
SELECT hwnd
CASE win
Select wmsg
case wm_create
'button0 = SetButton(win,10,40,80,26,"Close (X)",0x50001000,0x200,b0ID)
CASE WM_KEYDOWN
'SetFocus butt
if wParam = 13
print "VK_ENTER"
'InvalidateRect(edit1, 0, 1)
end if
'CASE WM_LBUTTONDOWN
' InvalidateRect(win, 0, 1)
'print "invalid"
CASE WM_COMMAND
controlID = LoWord(wParam) 'get control ID
notifyCode = HiWord(wParam) 'get notification message
select controlID
case b0ID
if notifycode = BN_CLICKED OR notifycode = 1
print "ENTER PRES!"
end if
case IDOK
if notifycode = 0
'get text and put it into buffer
SendMessage edit1, WM_GETTEXT, 256 , txbuff
buff = buff + crlf + txbuff
' print buff
SetText(edit2,buff )
'clear control edit1
SendMessage edit1, WM_SETTEXT, 0, ""
'set text to multi-line
'SendMessage edit2, WM_SETTEXT, 0,strptr(txbuff) + CRLF
end if
case IDCANCEL
print "ESCAPE"
end select
CASE WM_CLOSE
CloseWindow(win)
EndProgram
End Select
END SELECT
RETURN Default
END FUNCTION
Quotebut in overall it is not anything connected with HDC
Quotegeneral idea is to type text in edit control and then print that text on window
using GDI ...
Hi Aurel,
I never said that the your problem was related to any DC.
This is what I used in my demo to print that text on window,
sys hdc = GetDC(hWnd)
SetBkMode(hDC, TRANSPARENT)
TextOutW(hdc, 20, 30, sText, TextLen)
ReleaseDc(hdc)
and I did put it because you said
"
general idea is to type text in edit control and then print that text on window"I wanted an example as clear as possible.
I guess it is very difficult to understand each other...
I will have to work harder.
Aurel the awinh037 inc I got is 61,927 bytes, dated 2022-02-25 21:42.
Is it the right version?
I got it from AurelEdit (http://forum.it-berater.org/index.php?topic=5771.msg24579#msg24579)
Hi Aurel,
if I understand, the focus() thing belong to the past and we are treating new stuff.
Great!
About strange problem i have with CRLF which NOT execute after text then i need to add it to buffer before text.
I use the following code, it have the advantage to automatically scroll the text when needed. One more advantage is you do not have to copy the text back every time from edit1.
string sBuffer
long BufferLen
BufferLen = SendMessage(edit1, WM_GETTEXTLENGTH, 0, 0) 'Get character count
sBuffer = nuls(BufferLen) 'Build a buffer to get it
SendMessage(edit1, WM_GETTEXT, BufferLen + 1, sBuffer) 'Get the text
SendMessage(edit2, %EM_SETSEL, -1, -1) 'Move caret to the end
SendMessage(edit2, %EM_REPLACESEL, %TRUE, sBuffer & crlf) 'Insert text there
SendMessage(edit1, %WM_SETTEXT, 0, BYVAL 0) 'Reset input edit
Hi Pierre
It is about focus thing
I am not sure why you don't understand ?
Maybe my english really sucks...
Of course that is about focus and without IsDialogWindow ..IDOK message not work
yes rgis is only good way to get it properly and seems that work as it should be
and maybe you skip point where i was talking that i need it for my interpreter micro(A).
So when IDOK work ..focus or better to say carret is still in edit control and enable processing
what is under IDOK..i hope that you understand me now .
I don't need this functionality directly for OxygenBasic than indirectly for interpreter
which is written in Oxygenbasic...but as such could be useful in some other programs too.
all best
About your last posted code, you said:
seems all work fine ..only strange problem i have with CRLF which NOT execute after text then i need to add it to buffer
before text
If all works fine then it does what you want (except for the CRLF where I gave solution in my previous post)
but in this code, there is nothing special about focus.
Maybe, when your program start, you do not want IDOK to work if there is no focus/caret on edit1.
If it is so, try this...
case IDOK
if notifyCode = BN_CLICKED OR notifyCode = 1 then
if getfocus() = edit1 'Only if focus/caret is on edit1
long TextLen = SendMessageW(edit1, WM_GETTEXTLENGTH, 0, 0) 'Get character count (0x0E)
string sBuffer = nuls(TextLen) 'Build a buffer to get it
SendMessage(edit1, WM_GETTEXT, TextLen + 1, sBuffer) 'Get the text
SendMessage(edit2, %EM_SETSEL, -1, -1) 'Move caret to the end
SendMessage(edit2, %EM_REPLACESEL, %TRUE, sBuffer & crlf) 'Insert text there
SendMessage(edit1, %WM_SETTEXT, 0, BYVAL 0) 'Reset input edit
end if
end if
Else, if anybody see what I don't, please do tell...
Hi Pierre
all is fine
i must test all this in my interpreter
All work until i tested my old examples with arrow keys,tab key ,enter key not work
then i find that i need to modify message loop in a different way ,
why that is ..is because that keyboars buttons are used with Dialogs
so now message loop is this :
'/// message loop ///
WHILE GetMessage (wm,0,0,0)<>0
if IsDialogMessage(win,wm) = 0
TranslateMessage wm
DispatchMessage wm
else
TranslateMessage wm
DispatchMessage wm
end if
WEND
Hi Aurel,
Since you always do a TranslateMessage() and a DispatchMessage() no matter what.
In definitive your message loop is an equivalent to the following.
'/// message loop ///
WHILE GetMessage(wm, 0, 0, 0) <> 0
TranslateMessage(wm)
DispatchMessage(wm)
WEND
Can you post a little code example of what you got so we can see what it's all about.
Regard,
Pierre
Hi Pierre,
checkout IsDialogMessage. It does more than the name suggests. It modifies the keyboard code filters.
This should work:
'/// message loop ///
WHILE GetMessage (wm,0,0,0)<>0
IsDialogMessage(win,wm)
TranslateMessage wm
DispatchMessage wm
WEND
Hi Piere ...hi Charles
>> It modifies the keyboard code filters. <<
Yes that is a my main problem and of course i will post code
i try with this :
and kind a work :
'================================================================
'/// message loop ///
WHILE GetMessage (wm,0,0,0)<>0
if IsDialogMessage(win,wm) = 0
'TranslateMessage wm
'DispatchMessage wm
end if
if GetMessage (wm,0,0,0) <> 0
TranslateMessage wm
DispatchMessage wm
end if
WEND
'================================================================
Function WndProc (sys hwnd,wmsg,wparam,lparam) as sys callback
win = hwnd
SELECT hwnd
CASE win
Select wmsg
CASE WM_PAINT
'paintstruct ps
BeginPaint win,ps
BitBlt(hDC, 0, 0, ww, wh, hdcMem, 0, 0, SRCCOPY)
'InvalidateRect(win, 0, 0)
'
ReleaseDC( win, hDC)
EndPaint win,ps
'CASE WM_SETFOCUS
' SetFocus win
'processing windows messages by Interpreter..................................................
CASE WM_MOUSEMOVE
'hMouseX = LoWord(lParam)
'hMouseY = HiWord(lParam)
'call block winMsg
if pos_wmMouseMove > 0
hMouseX = LoWord(lParam)
hMouseY = HiWord(lParam)
tc = pos_wmMouseMove : tokInterpreter()
tc = 0
end if
'keybord event...............................................................................
CASE WM_KEYDOWN
hWParam = wParam
'call block winMsg
if pos_wmKeyDown <> 0
'print "KEYDOWN:" + str(pos_wmKeyDown)
tc = pos_wmKeyDown : tokInterpreter()
tc = 0
end if
'............................................................................................
CASE WM_COMMAND
controlID = LoWord(wParam) 'get control ID
notifyCode = HiWord(wParam) 'get notification message
'hWParam = wParam
Select controlID
hwParam = controlID
CASE IDOK
'call block winMsg
if notifycode = 0
if pos_wmCommand > 0
tc = pos_wmCommand : tokInterpreter()
tc = 0
end if
end if
'CASE IDCANCEL
' print "ID_CANCEL"
End Select
..above is whole code i currently use in my interpreter
so as you may see i need both
Sorry Charles your method not work
because when i entering text in edit control insted of one sign i get 4 signs pressing one
keyboard key.. i don't know why but might be connected with tab sequence
default is 4 i think
so my question is what IsDialogMessage do ?
is just TranslateMessage or DispatchMessage or both ?
also ..well i found one guy on google group use it with PeekMessage
hmm i can try :
here is C code i guess:
while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
BOOL bRet = ::GetMessage(&msg, NULL, 0, 0);
if(bRet == -1 || !bRet)
{
m_bQuit = TRUE;
continue;
}
HWND hWnd = msg.hwnd;
switch(msg.message)
{
//Find the parent dialog if there is one so IsDialogMessage will
work
case WM_CHAR:
case WM_SYSCHAR:
case WM_KEYUP:
case WM_KEYDOWN:
case WM_SYSKEYUP:
case WM_SYSKEYDOWN:
{
HWND hWndParent = _GetAncestor(hWnd, GA_PARENT);
if(hWndParent && hWndParent != HWND_DESKTOP)
hWnd = hWndParent;
}
break;
}
if(!IsDialogMessage(hWnd, &msg))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
i try under peekMessage and not work ...
case else
'peekmsg
if PeekMessage (wm,0,0,0,Pm_Remove)>0 ' //peek
'iF wm.message = WM_QUIT : DeleteDC(hdc) : end if
TranslateMessage (wm)
DispatchMessage (wm)
else
IsDialogMessage(win,wm)
TranslateMessage (wm)
DispatchMessage (wm)
'end if
end if
strange .no mather i try i have keyboard key delay
not respond well
Which Oxygen version are you using? I've picked up a problem with 060 which might be connected.
Charles i am using old A043 and so far all api calls work well
i really don't know how this work in PowerBasic or PureBasic or FreeBasic
because i cannot found any similar example
Charles
the closest example i found here posted by Jose
and is about subclassing textbox or edit control
i compiled it in A043 and seems that work well i add small char[] buffer to view entered text
$ filename "SubClassText.exe"
uses rtl32
uses MinWin
uses User
uses Comctl
char txBuff[256]
sys hEdit
string crlf = chr(13) + chr(10)
#lookahead
%GWLP_WNDPROC = -4
function WinMain() as sys
WndClass wc
MSG wm
sys inst = GetModuleHandle 0
sys hwnd, wwd, wht, wtx, wty, tax
wc.style = CS_HREDRAW or CS_VREDRAW
wc.lpfnWndProc = &WndProc
wc.cbClsExtra = 0
wc.cbWndExtra = 0
wc.hInstance = GetModuleHandle 0
wc.hIcon=LoadIcon 0, IDI_APPLICATION
wc.hCursor=LoadCursor 0,IDC_ARROW
wc.hbrBackground = GetStockObject WHITE_BRUSH
wc.lpszMenuName =0
wc.lpszClassName =@"Demo"
RegisterClass (&wc)
Wwd = 320 : Wht = 200
Tax = GetSystemMetrics SM_CXSCREEN
Wtx = (Tax - Wwd) /2
Tax = GetSystemMetrics SM_CYSCREEN
Wty = (Tax - Wht) /2
hwnd = CreateWindowEx(0,wc.lpszClassName,"OXYGEN BASIC",WS_OVERLAPPEDWINDOW,Wtx,Wty,Wwd,Wht,0,0,inst,0)
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, _
"Edit", _
"", _
WS_CHILD OR WS_VISIBLE OR WS_TABSTOP, _
20, 30, _
250, 25, _
hWnd, 102, _
inst, 0)
SetWindowSubclass hEdit, &EditSubclassProc, 102, 0
SetFocus hEdit
ShowWindow hwnd,SW_SHOW
UpdateWindow hwnd
WHILE GetMessage(&wm, 0, 0, 0) > 0
IF IsDialogMessage(hWnd, &wm) = 0 THEN
TranslateMessage(&wm)
DispatchMessage(&wm)
END IF
WEND
End Function
function WndProc (sys hWnd, uint wMsg, sys wParam, sys lparam) as sys callback
'==================================================================
SELECT wMsg
CASE WM_CREATE
EXIT FUNCTION
CASE WM_COMMAND
SELECT CASE LOWORD(wParam)
'test idok - "ENTER key pressed!"
Case IDOK
if hiword(wparam) = BN_CLICKED
' get editbox text
SendMessage hEdit, WM_GETTEXT, 256, strptr txbuff
'show message box
print "ENTER key pressed!" + crlf + txbuff
end if
CASE IDCANCEL
' // If the Escape key has been pressed...
IF HIWORD(wParam) = BN_CLICKED THEN
' // ... close the application by sending a WM_CLOSE message
SendMessage hwnd, WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
END SELECT
CASE WM_DESTROY
PostQuitMessage 0
END SELECT
function = DefWindowProc hWnd,wMsg,wParam,lParam
end function ' WndProc
FUNCTION EditSubclassProc (sys hWnd, uint wMsg, sys wParam, sys lparam, uIdSubclass, dwRefData) as sys callback
SELECT CASE wMsg
CASE WM_DESTROY
' // REQUIRED: Remove control subclassing
RemoveWindowSubclass hwnd, &EditSubclassProc, uIdSubclass
CASE WM_KEYDOWN
SetWindowText GetParent(hwnd), "ASCII " & STR(wParam)
END SELECT
FUNCTION = DefSubclassProc(hwnd, wMsg, wParam, lParam)
END FUNCTION
WinMain()
Jose example use subclassed edit control which is fine for
his example ....
but also work in my case with one my example
now because notification message is BN_CLICKED
i used before notifycode = 0
and probably because of this there is delay in execution
how will work in combination with WM_KEYDOWN ..i need to test
CASE WM_COMMAND
controlID = LoWord(wParam) 'get control ID
notifyCode = HiWord(wParam) 'get notification message
'hWParam = wParam
Select controlID
hwParam = controlID
CASE IDOK
'call block winMsg
if notifycode = BN_CLICKED
if pos_wmCommand > 0
tc = pos_wmCommand : tokInterpreter()
tc = 0
end if
end if
'CASE IDCANCEL
' print "ID_CANCEL"
and message loop is here :
'/// message loop ///
WHILE GetMessage (wm,0,0,0) > 0
if IsDialogMessage(win,wm) = 0
TranslateMessage wm
DispatchMessage wm
end if
WEND
..of course i must thanks to Jose ;)
I have never used dialogs, but that message loop now makes sense:
WHILE GetMessage (wm,0,0,0) > 0
if IsDialogMessage(win,wm) = 0
TranslateMessage wm
DispatchMessage wm
end if
WEND
However, if your intention is to pickup keyboard codes without being restricted by focus you can check all the unfiltered window handles and keyboard codes coming through the message loop.
You can also use this information to directly issue your own WM_COMMAND messages to WndProc with the main hWnd. This is the message loop I use in tools\Peroxide.o2bas which uses buttons and edit-boxes but has no menu or accelerator table
while bRet := GetMessage (wm, 0, 0, 0)
if bRet==-1
mbox "windows message loop error "
exit while
else
if wm.message=WM_KEYDOWN
select wm.wparam
'
case 0x1B 'Esc
SendMessage hwnd,WM_DESTROY,0,0
continue do
case 83 'S
if GetAsyncKeyState(VK_CONTROL) and 0x8000
SendMessage hWnd,WM_COMMAND, 4002, 0 'to save file
continue do
endif
case 69 'E
if GetAsyncKeyState(VK_CONTROL) and 0x8000
SendMessage hWnd,WM_COMMAND, 4003, 0 'to run file
continue do
endif
case VK_F9 'save file
SendMessage hWnd,WM_COMMAND, 4002, 0 'to save file
continue do
case VK_F5 'exec file
SendMessage hWnd,WM_COMMAND, 4003, 0 'to run file
continue do
case VK_F2 'color
SendMessage hWnd,WM_COMMAND, 4005, 0 'to colorize
continue do
case VK_F1
DisplayHelp
continue do
case VK_F3 '
SendMessage hWnd,WM_COMMAND, 4001, 0 'to execute search
case VK_F4 '
SendMessage hWnd,WM_COMMAND, 4004, 0 'to execute word search
case 0x0D 'CR / Enter
if wm.hwnd=w[4]
SendMessage hWnd,WM_COMMAND, 4001, 0 'to execute search
continue do
endif
end select
endif
TranslateMessage &wm
DispatchMessage &wm
endif
wend
Thank you Charles
I know that i miss something and that is :
if GetAsyncKeyState(VK_CONTROL) and 0x8000
GetAsyncKeyState ..PeterW use in his programs
also i don't use Dialogs in my programs
but..
i do one little trick in my interpreter to
make it work ..at first i don't figured why work
but now i understand..i do this
// micro(A) code //
while wp ! 27 ' means NOT
'do nothing
wend
and that small empty loop enable use of arrow keys ;)
all best
Charles> checkout IsDialogMessage. It does more than the name suggests.
Bill> Determines whether a message is intended for the specified dialog box and, if it is, processes the message.
Yes, you are quite right, I should have pay more attention...
Charles> I have never used dialogs, but that message loop now makes sense...
Could not agree more...
Aurel> so my question is what IsDialogMessage do ? is just TranslateMessage or DispatchMessage or both ?
Aurel, the message will be proceed by either IsDialogMessage or TranslateMessage/DispatchMessage, not both.
The remark section of IsDialogMessage is usefull:
If IsDialogMessage() return zero the message has not been processed so use TranslateMessage/DispatchMessage.
Although the IsDialogMessage function is intended for modeless dialog boxes, you can use it with any window that contains controls,
enabling the windows to provide the same keyboard selection as is used in a dialog box.
When IsDialogMessage processes a message,
it checks for keyboard messages and converts them into selections for the corresponding dialog box.
For example, the TAB key, when pressed, selects the next control or group of controls,
and the DOWN ARROW key, when pressed, selects the next control in a group.
Because the IsDialogMessage function performs all necessary translating and dispatching of messages,
a message processed by IsDialogMessage must not be passed to the TranslateMessage or DispatchMessage function.
IsDialogMessage sends WM_GETDLGCODE messages to the dialog box procedure to determine which keys should be processed.
Here is some code to demo WM_GETDLGCODE/DLGC_WANTALLKEYS on an edit control.
The control will get all keystroke, including tab, enter, esc, etc, etc.
//KickSwitch -32
//KickEnd
uses rtl32
uses MinWin
uses User
uses Comctl
sys hEdit
#lookahead
%Edit 101
%GWLP_WNDPROC -4
%DEFAULT_GUI_FONT 17
%WM_GETDLGCODE 0x0087
%DLGC_WANTARROWS 0x0001 // Direction keys.
%DLGC_WANTTAB 0x0002 // TAB key.
%DLGC_WANTALLKEYS 0x0004 // All keyboard input.
%DLGC_WANTMESSAGE 0x0004 // All keyboard input (the application passes this message in the MSG structure to the control).
%DLGC_HASSETSEL 0x0008 // EM_SETSEL messages.
%DLGC_DEFPUSHBUTTON 0x0010 // Default push button.
%DLGC_UNDEFPUSHBUTTON 0x0020 // Non-default push button.
%DLGC_RADIOBUTTON 0x0040 // Radio button.
%DLGC_WANTCHARS 0x0080 // WM_CHAR messages.
%DLGC_STATIC 0x0100 // Static control.
%DLGC_BUTTON 0x2000 // Button.
'____________________________________________________________________________
function WinMain() as sys
WndClass WindowClass
MSG WindowMessage
long WindowWidth, WindowHeight, WindowPosX, WindowPosY
sys hWnd
sys inst = GetModuleHandle(0)
WindowClass.style = CS_HREDRAW | CS_VREDRAW
WindowClass.lpfnWndProc = &WndProc
WindowClass.cbClsExtra = 0
WindowClass.cbWndExtra = 0
WindowClass.hInstance = GetModuleHandle(0)
WindowClass.hIcon = LoadIcon(0, IDI_APPLICATION)
WindowClass.hCursor = LoadCursor(0,IDC_ARROW)
WindowClass.hbrBackground = 16
WindowClass.lpszMenuName = 0
WindowClass.lpszClassName = @"OXYGEN BASIC"
RegisterClass (WindowClass)
WindowWidth = 320
WindowHeight = 100
WindowPosX = (GetSystemMetrics(SM_CXSCREEN) - WindowWidth) / 2
WindowPosY = (GetSystemMetrics(SM_CYSCREEN) - WindowHeight) / 2
hWnd = CreateWindowEx(WS_EX_STATICEDGE, WindowClass.lpszClassName,
"WM_GETDLGCODE demo", WS_OVERLAPPEDWINDOW,
WindowPosX, WindowPosY, WindowWidth, WindowHeight, 0, 0, inst, 0)
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit", "Try [tab] [arrows] [enter]",
WS_CHILD OR WS_VISIBLE OR WS_TABSTOP,
20, 30, 270, 20,
hWnd, Edit, inst, 0)
SendMessage(hEdit, WM_SETFONT, GetStockObject(DEFAULT_GUI_FONT), TRUE)
SetWindowSubclass(hEdit, &EditSubclassProc, Edit, 0)
SetFocus(hEdit)
ShowWindow(hWnd, SW_SHOW)
UpdateWindow(hWnd)
while GetMessage(&WindowMessage, 0, 0, 0) > 0
if IsDialogMessage(hWnd, &WindowMessage) = 0
'if IsDialogMessage() return zero the message has not been processed
'so use TranslateMessage/DispatchMessage
TranslateMessage(&WindowMessage)
DispatchMessage(&WindowMessage)
end if
wend
end function
'____________________________________________________________________________
function WndProc(sys hWnd, uint wMsg, sys wParam, sys lparam) as sys callback
select wMsg
case WM_DESTROY
RemoveWindowSubclass(hEdit, &EditSubclassProc, Edit) 'unsubclass
PostQuitMessage(0)
end select
function = DefWindowProc(hWnd, wMsg, wParam, lParam)
end function
'____________________________________________________________________________
function EditSubclassProc(sys hEdit, uint wMsg, sys wParam, sys lparam, uIdSubclass, dwRefData) as sys callback
select case wMsg
case WM_GETDLGCODE
'DLGC_WANTARROWS 0x0001 Direction keys.
'DLGC_WANTTAB 0x0002 TAB key.
'DLGC_WANTALLKEYS 0x0004 All keyboard input.
'DLGC_WANTMESSAGE 0x0004 All keyboard input (the application passes this message in the MSG structure to the control).
'DLGC_HASSETSEL 0x0008 EM_SETSEL messages.
'DLGC_DEFPUSHBUTTON 0x0010 Default push button.
'DLGC_UNDEFPUSHBUTTON 0x0020 Non-default push button.
'DLGC_RADIOBUTTON 0x0040 Radio button.
'DLGC_WANTCHARS 0x0080 WM_CHAR messages.
'DLGC_STATIC 0x0100 Static control.
'DLGC_BUTTON 0x2000 Button.
return DLGC_WANTALLKEYS
case WM_CHAR
SetWindowText(GetParent(hEdit), "WM_CHAR " & str(wParam))
select case wParam
case 1 'control-a
SendMessage(hEdit, %EM_SETSEL, 0, -1) 'select everything
return(0) 'do not forward Control-A
case 48 TO 57, 45, 46 '0 to 9, minus, dot
return(0) 'do not forward numbers, minus, dot
case 65 TO 90 'A to Z
'return(0) 'do not forward uppercase A to Z
case 97 TO 122 'a to z
'return(0) 'do not forward lowercase a to z
case 9 'TAB
SetWindowText(hEdit, "tab key pressed")
return(0) 'do not forward TAB
case 13 'ENTER
SetWindowText(hEdit, "enter key pressed")
return(0) 'do not forward ENTER
case 27 'ESC
SendMessage(GetParent(hEdit), WM_CLOSE, 0, 0)
return(0)
end select
case WM_KEYDOWN, WM_KEYUP
SetWindowText(GetParent(hEdit), "WM_KEY " & str(wParam))
select case wParam
case 37 'left arrow
SendMessage(hEdit, %EM_SETSEL, 0, 1) 'select first char
return(0) 'rem to accept left arrow key, use up and down
case 39 'right arrow
SendMessage(hEdit, %EM_SETSEL, 1, 2) 'select second char
return(0) 'rem to accept right arrow key, use up and down
end select
end select
function = DefSubclassProc(hEdit, wMsg, wParam, lParam) 'forward message to edit control
end function
'____________________________________________________________________________
WinMain()
'____________________________________________________________________________
'
Quote from: Zlatko Vid on May 23, 2023, 07:10:15 AM// micro(A) code //
while wp ! 27 ' means NOT
'do nothing
wend
and that small empty loop enable use of arrow keys ;)
You not even insert an "DOEVENTS()" or a "SLEEP"?
If so this looks to me like an endless loop which is not a construct that should be used - is it?
Thanks Pierre,
I'll include your IsDialog example in demos\wingui\, (some changes to the includes)
'uses rtl32
uses corewin
sys hEdit
%Edit 101
%GWLP_WNDPROC -4
%DEFAULT_GUI_FONT 17
%WM_GETDLGCODE 0x0087
%DLGC_WANTARROWS 0x0001 // Direction keys.
%DLGC_WANTTAB 0x0002 // TAB key.
%DLGC_WANTALLKEYS 0x0004 // All keyboard input.
%DLGC_WANTMESSAGE 0x0004 // All keyboard input (the application passes this message in the MSG structure to the control).
%DLGC_HASSETSEL 0x0008 // EM_SETSEL messages.
%DLGC_DEFPUSHBUTTON 0x0010 // Default push button.
%DLGC_UNDEFPUSHBUTTON 0x0020 // Non-default push button.
%DLGC_RADIOBUTTON 0x0040 // Radio button.
%DLGC_WANTCHARS 0x0080 // WM_CHAR messages.
%DLGC_STATIC 0x0100 // Static control.
%DLGC_BUTTON 0x2000 // Button.
'____________________________________________________________________________
function WinMain() as sys
WndClass WindowClass
MSG WindowMessage
long WindowWidth, WindowHeight, WindowPosX, WindowPosY
sys hWnd
sys inst = GetModuleHandle(0)
WindowClass.style = CS_HREDRAW | CS_VREDRAW
WindowClass.lpfnWndProc = &WndProc
WindowClass.cbClsExtra = 0
WindowClass.cbWndExtra = 0
WindowClass.hInstance = GetModuleHandle(0)
WindowClass.hIcon = LoadIcon(0, IDI_APPLICATION)
WindowClass.hCursor = LoadCursor(0,IDC_ARROW)
WindowClass.hbrBackground = 16
WindowClass.lpszMenuName = 0
WindowClass.lpszClassName = @"OXYGEN BASIC"
RegisterClass (WindowClass)
WindowWidth = 320
WindowHeight = 100
WindowPosX = (GetSystemMetrics(SM_CXSCREEN) - WindowWidth) / 2
WindowPosY = (GetSystemMetrics(SM_CYSCREEN) - WindowHeight) / 2
hWnd = CreateWindowEx(WS_EX_STATICEDGE, WindowClass.lpszClassName,
"WM_GETDLGCODE demo", WS_OVERLAPPEDWINDOW,
WindowPosX, WindowPosY, WindowWidth, WindowHeight, 0, 0, inst, 0)
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit", "Try [tab] [arrows] [enter]",
WS_CHILD OR WS_VISIBLE OR WS_TABSTOP,
20, 30, 270, 20,
hWnd, Edit, inst, 0)
SendMessage(hEdit, WM_SETFONT, GetStockObject(DEFAULT_GUI_FONT), TRUE)
SetWindowSubclass(hEdit, &EditSubclassProc, Edit, 0)
SetFocus(hEdit)
ShowWindow(hWnd, SW_SHOW)
UpdateWindow(hWnd)
while GetMessage(&WindowMessage, 0, 0, 0) > 0
if IsDialogMessage(hWnd, &WindowMessage) = 0
'if IsDialogMessage() return zero the message has not been processed
'so use TranslateMessage/DispatchMessage
TranslateMessage(&WindowMessage)
DispatchMessage(&WindowMessage)
end if
wend
end function
'____________________________________________________________________________
function WndProc(sys hWnd, uint wMsg, sys wParam, sys lparam) as sys callback
select wMsg
case WM_DESTROY
RemoveWindowSubclass(hEdit, &EditSubclassProc, Edit) 'unsubclass
PostQuitMessage(0)
end select
function = DefWindowProc(hWnd, wMsg, wParam, lParam)
end function
'____________________________________________________________________________
function EditSubclassProc(sys hEdit, uint wMsg, sys wParam, sys lparam, uIdSubclass, dwRefData) as sys callback
select case wMsg
case WM_GETDLGCODE
'DLGC_WANTARROWS 0x0001 Direction keys.
'DLGC_WANTTAB 0x0002 TAB key.
'DLGC_WANTALLKEYS 0x0004 All keyboard input.
'DLGC_WANTMESSAGE 0x0004 All keyboard input (the application passes this message in the MSG structure to the control).
'DLGC_HASSETSEL 0x0008 EM_SETSEL messages.
'DLGC_DEFPUSHBUTTON 0x0010 Default push button.
'DLGC_UNDEFPUSHBUTTON 0x0020 Non-default push button.
'DLGC_RADIOBUTTON 0x0040 Radio button.
'DLGC_WANTCHARS 0x0080 WM_CHAR messages.
'DLGC_STATIC 0x0100 Static control.
'DLGC_BUTTON 0x2000 Button.
return DLGC_WANTALLKEYS
case WM_CHAR
SetWindowText(GetParent(hEdit), "WM_CHAR " & str(wParam))
select case wParam
case 1 'control-a
SendMessage(hEdit, %EM_SETSEL, 0, -1) 'select everything
return(0) 'do not forward Control-A
case 48 TO 57, 45, 46 '0 to 9, minus, dot
return(0) 'do not forward numbers, minus, dot
case 65 TO 90 'A to Z
'return(0) 'do not forward uppercase A to Z
case 97 TO 122 'a to z
'return(0) 'do not forward lowercase a to z
case 9 'TAB
SetWindowText(hEdit, "tab key pressed")
return(0) 'do not forward TAB
case 13 'ENTER
SetWindowText(hEdit, "enter key pressed")
return(0) 'do not forward ENTER
case 27 'ESC
SendMessage(GetParent(hEdit), WM_CLOSE, 0, 0)
return(0)
end select
case WM_KEYDOWN, WM_KEYUP
SetWindowText(GetParent(hEdit), "WM_KEY " & str(wParam))
select case wParam
case 37 'left arrow
SendMessage(hEdit, %EM_SETSEL, 0, 1) 'select first char
return(0) 'rem to accept left arrow key, use up and down
case 39 'right arrow
SendMessage(hEdit, %EM_SETSEL, 1, 2) 'select second char
return(0) 'rem to accept right arrow key, use up and down
end select
end select
function = DefSubclassProc(hEdit, wMsg, wParam, lParam) 'forward message to edit control
end function
'
WinMain()
QuoteYou not even insert an "DOEVENTS()" or a "SLEEP"?
If so this looks to me like an endless loop which is not a construct that should be used - is it?
Theo
This loop is just executed when key is pressed not all the time
here is whole block of micro(A) code :
WinMsg wmKEYDOWN
hWparam wp
'vkLEFT ?
if wp = 37
if freq > 1
freq = freq - 1 : length = cons/freq : dlen = int(length*5)
if dx > 0
dx = ox - (dlen/2)
DisplayUpdate() : DrawDipol()
endif
endif
endif
'vkRIGHT ?
if wp = 39
if freq < 2500
freq = freq + 1 : length = cons/freq : dlen = int(length*5)
if dx < 400
dx = ox - (dlen/2)
DisplayUpdate() : DrawDipol()
endif
endif
endif
'select mode
while wp ! 27
'wait
wend
EndWm
QuoteAurel, the message will be proceed by either IsDialogMessage or TranslateMessage/DispatchMessage, not both.
Hi Piere
I understand that part now but not first time i try ..
I really never used this API function before
Also thanks on explanation and on example .
And also you must understand that i need it for my interpreter
or in another words this events execute interpreter loop.
here is that part ..of course i will add more events but for now it is...as is :
processing windows messages by Interpreter..................................................
CASE WM_MOUSEMOVE
'hMouseX = LoWord(lParam)
'hMouseY = HiWord(lParam)
'call block winMsg
if pos_wmMouseMove > 0
hMouseX = LoWord(lParam)
hMouseY = HiWord(lParam)
tc = pos_wmMouseMove : tokInterpreter()
tc = 0
end if
'keybord event...............................................................................
CASE WM_KEYDOWN
hWParam = wParam
'call block winMsg
if pos_wmKeyDown > 0
'print "KEYDOWN:" + str(pos_wmKeyDown)
tc = pos_wmKeyDown : tokInterpreter()
tc = 0
end if
'...........................................................................................
CASE WM_KEYUP
hWParam = wParam
'call block winMsg
if pos_wmKeyUp > 0
'print "KEYDOWN:" + str(pos_wmKeyDown)
tc = pos_wmKeyUp : tokInterpreter()
tc = 0
end if
'............................................................................................
CASE WM_COMMAND
controlID = LoWord(wParam) 'get control ID
notifyCode = HiWord(wParam) 'get notification message
'hWParam = wParam
Select controlID
hwParam = controlID
CASE IDOK
'call block winMsg
if notifycode = BN_CLICKED
if pos_wmCommand > 0
tc = pos_wmCommand : tokInterpreter()
tc = 0
end if
end if
CASE IDCANCEL
'call block winMsg
if notifycode = BN_CLICKED
if pos_wmCommand > 0
tc = pos_wmCommand : tokInterpreter()
tc = 0
end if
end if