Page 1 of 1

#EM_SET/GETMODIFY Question

Posted: Fri May 04, 2007 10:45 pm
by milan1612
Hi,

Run this code with debugger enabled:

Code: Select all

OpenWindow(0, 5,5,400,400,"test",#PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CreateGadgetList(WindowID(0))
EditorGadget(1, 10,10,300,300)

Debug Str(SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0))
SendMessage_(GadgetID(1), #EM_SETMODIFY, #True, 0)
Debug Str(SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0))

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
It always shows -1 ???
The MSDN says that after the creation of a Richedit (which the EditorGadget uses) the MODIFY Flag is set to 0:
(http://msdn.microsoft.com/library/defau ... modify.asp)

What am I doing wrong?

Thanks, in advance
milan1612

Posted: Sat May 05, 2007 12:43 am
by Fluid Byte
I just tested it and discovered the reason why you always get -1, regardless of wich modification state you set. It's related to the way PB creates the RichEdit control. Although I can't tell you exactly what causes this but I won't happen if you create it via API:

Code: Select all

OpenLibrary(0,"riched32")

OpenWindow(0,5,5,400,400,"test",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)

hwndRichEdit = CreateWindowEx_(#WS_EX_CLIENTEDGE,"RichEdit20A",0,#WS_CHILD | #WS_VISIBLE,10,10,300,300,WindowID(0),0,0,0)

Debug SendMessage_(hwndRichEdit,#EM_GETMODIFY,0,0)
SendMessage_(hwndRichEdit,#EM_SETMODIFY,#True,0)
Result = SendMessage_(hwndRichEdit,#EM_GETMODIFY,0,0)
Debug SendMessage_(hwndRichEdit,#EM_GETMODIFY,0,0)

If Result : Debug "Content has been modified!" : EndIf

While WaitWindowEvent() ! 16 : Wend

DestroyWindow_(hwndRichEdit)
Weird thing is that still returns -1 if it has been modfied. I didn't expect a negative value but MSDN says that the result will be a "non-zero". So it can be >0 or in this case <0.

Posted: Sat May 05, 2007 11:15 am
by milan1612
Thanks for your suggestion, I will use the API.
Nevertheless it's weird. :?

Posted: Thu May 10, 2007 7:39 pm
by Xombie
Look at this...

Code: Select all

OpenWindow(0, 5,5,400,400,"test",#PB_Window_ScreenCentered | #PB_Window_SystemMenu) 
CreateGadgetList(WindowID(0)) 
EditorGadget(1, 10,10,300,300) 

a.l = SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0)
Debug Bin(a)
SendMessage_(GadgetID(1), #EM_SETMODIFY, #True, 0) 
a = SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0)
Debug Bin(a)
SendMessage_(GadgetID(1), #EM_SETMODIFY, #False, 0) 
a = SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0)
Debug Bin(a)
SendMessage_(GadgetID(1), #EM_SETMODIFY, #True, 0) 
a = SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0)
Debug Bin(a)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
... and then this ...

Code: Select all

OpenWindow(0, 5,5,400,400,"test",#PB_Window_ScreenCentered | #PB_Window_SystemMenu) 
CreateGadgetList(WindowID(0)) 
EditorGadget(1, 10,10,300,300) 

a.l = SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0)
Debug a & 1
SendMessage_(GadgetID(1), #EM_SETMODIFY, #True, 0) 
a = SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0)
Debug a & 1
SendMessage_(GadgetID(1), #EM_SETMODIFY, #False, 0) 
a = SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0)
Debug a & 1

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Posted: Thu May 10, 2007 7:53 pm
by milan1612
Sorry I've never used binary operators before.
Could you please explain what you want to say with this?

Posted: Thu May 10, 2007 8:14 pm
by Xombie
Well, you can disregard the first block of code. The second block should return the value you're looking for, right?

My point in showing the binary (in the first code block) is that all 1s signify TRUE while 0 is still FALSE. So by doing a "a & 1" (in the second code block) you return simply 1 for TRUE and 0 for FALSE.

I don't know. Possibly a signed/unsigned variable issue? After all, MSDN says that EM_GETMODIFY returns non-zero when TRUE. -1 is non-zero.

Or were you concerned primarily with the flag not being zero when the control is first created? Maybe PB does something different at creation time that flips the modified flag? If that part worries you, use a EM_SETMODIFY with 0 immediately following the EditorGadget() call.

Posted: Thu May 10, 2007 8:47 pm
by milan1612
That's the point: Set EM_SETMODIFY to True. Then read it out by EM_GETMODIFY
and you will get False.

Posted: Thu May 10, 2007 9:37 pm
by Xombie
I'll try to simplify...

Code: Select all

Procedure.l EM_GetModified(Gadget.l)
   ProcedureReturn SendMessage_(GadgetID(1), #EM_GETMODIFY, 0, 0) & 1
EndProcedure
OpenWindow(0, 5,5,400,400,"test",#PB_Window_ScreenCentered | #PB_Window_SystemMenu) 
CreateGadgetList(WindowID(0)) 
EditorGadget(1, 10,10,300,300) 

Debug EM_GetModified(1)
SendMessage_(GadgetID(1), #EM_SETMODIFY, #True, 0) 
Debug EM_GetModified(1)
SendMessage_(GadgetID(1), #EM_SETMODIFY, #False, 0) 
Debug EM_GetModified(1)
SendMessage_(GadgetID(1), #EM_SETMODIFY, #True, 0) 
Debug EM_GetModified(1)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
... or am I really, really just missing the point? That very small procedure returns the correct value whether you set true or false. You could even make an EM_SetModified() procedure if you like.

Posted: Thu May 10, 2007 9:48 pm
by milan1612
Ok I got it. :oops:

BTW I'm getting 1,1,0,1.
That means when the Editor is created the Modified Flag is set to True.
The MSDN says it will be set to Zero. :?: :?: :?:
Thanks in advance...

Posted: Thu May 10, 2007 11:56 pm
by Xombie
Not sure. Like I said just a little bit ago, perhaps PureBasic is doing something internally when it creates the rich text control that causes the modified flag to be set to TRUE. If it really bothers you, set the modified flag to FALSE immediately after you call EditorGadget().

Hope that helps.

Re: #EM_SET/GETMODIFY Question

Posted: Mon Jul 17, 2017 9:01 pm
by skywalk
Anyone else see false modified flags with simple keystrokes?
Does this workaround have any issues?

Code: Select all

EnableExplicit
Global.i edr_CB, evWW, ri
#VKeyIsDOWN = 4096
Macro edr_IsModified(hG)
  ; Requires CallBack to remove false positives with some keystrokes.
  Bool(SendMessage_(hG, #EM_GETMODIFY, 0, 0))
EndMacro
Procedure.i E_CB(hW, msg, wP, lP)
  Protected.i ri = CallWindowProc_(edr_CB, hW, msg, wP, lP)
  Protected.i notmod
  Select msg
  Case #WM_KILLFOCUS  ; Lost focus
    Debug "lost focus"
  Case #WM_RBUTTONDOWN
  Case #WM_KEYDOWN
    ; Cannot rely solely on IsModified() since some keystrokes/complex selections give false positive.
    ; Instead, ignore complex cases via key states.
    If GetKeyState_(#VK_ESCAPE) & #VKeyIsDown   ; & $8000
      notmod = 1
    EndIf
    If GetKeyState_(#VK_UP) & #VKeyIsDown
      notmod = 1
    EndIf
    If GetKeyState_(#VK_DOWN) & #VKeyIsDown
      notmod = 1
    EndIf
    If GetKeyState_(#VK_LEFT) & #VKeyIsDown
      notmod = 1
    EndIf
    If GetKeyState_(#VK_RIGHT) & #VKeyIsDown
      notmod = 1
    EndIf
    If GetKeyState_(#VK_SHIFT) & #VKeyIsDown
      notmod = 1
    EndIf
    If GetKeyState_(#VK_MENU) & #VKeyIsDown
      notmod = 1
    EndIf
    If GetKeyState_(#VK_CONTROL) & #VKeyIsDown
      If GetKeyState_(#VK_C) & #VKeyIsDown
        notmod = 1
      ElseIf GetKeyState_(#VK_V) & #VKeyIsDown
        notmod = 0
      Else
        notmod = 1
      EndIf
    EndIf
    If notmod = 0
      If edr_IsModified(GadgetID(0))
        Debug "Modified"
      EndIf
    EndIf
  EndSelect
  ProcedureReturn ri
EndProcedure
OpenWindow(0, 5, 5, 400, 400 ,"Editor Modified?", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
EditorGadget(0, 10, 10, 300, 300)
SendMessage_(GadgetID(0), #EM_SETMODIFY, 0, 0)  ; Disable modified flag on initial gadget creation.
edr_CB = SetWindowLongPtr_(GadgetID(0), #GWLP_WNDPROC, @E_CB())
Repeat
  evWW = WaitWindowEvent()
  If EventGadget() = 0
    ;ri = edr_IsModified(GadgetID(0))
    ;If ri
    ;  Debug "modified in PB event loop"
    ;  SendMessage_(GadgetID(0), #EM_SETMODIFY, 0, 0)
    ;EndIf
  EndIf
  If evWW = #PB_Event_CloseWindow
    Break
  EndIf
ForEver