#EM_SET/GETMODIFY Question

Windows specific forum
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

#EM_SET/GETMODIFY Question

Post 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
Windows 7 & PureBasic 4.4
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post 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.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post by milan1612 »

Thanks for your suggestion, I will use the API.
Nevertheless it's weird. :?
Windows 7 & PureBasic 4.4
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post 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
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post by milan1612 »

Sorry I've never used binary operators before.
Could you please explain what you want to say with this?
Windows 7 & PureBasic 4.4
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post 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.
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post by milan1612 »

That's the point: Set EM_SETMODIFY to True. Then read it out by EM_GETMODIFY
and you will get False.
Windows 7 & PureBasic 4.4
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post 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.
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post 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...
Windows 7 & PureBasic 4.4
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post 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.
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: #EM_SET/GETMODIFY Question

Post 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
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Post Reply