Jump to content

RichTextBox image problem


Recommended Posts

Hi,

When I run the example script of _GUICtrlRichEdit_Create in my windows 10 machine, i can drag & drop an image and it appears in the richtextbox, but if I do the same on windows 7, the image is converted to an object and the richtextbox only shows the icon for images.

How can i replicate the windows 10 behavior on windows 7? Is it posible?

Here is the code:

#include <GUIConstantsEx.au3>
#include <GuiRichEdit.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    Local $hGui, $hRichEdit, $iMsg
    $hGui = GUICreate("Example (" & StringTrimRight(@ScriptName, StringLen(".exe")) & ")", 320, 350, -1, -1)
    $hRichEdit = _GUICtrlRichEdit_Create($hGui, "DROP AN IMAGE HERE!"&@CRLF, 10, 10, 300, 220, _
            BitOR($ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL))
    GUISetState(@SW_SHOW)

    While True
        $iMsg = GUIGetMsg()
        Select
            Case $iMsg = $GUI_EVENT_CLOSE
                _GUICtrlRichEdit_Destroy($hRichEdit) ; needed unless script crashes
                ; GUIDelete()   ; is OK too
                Exit
        EndSelect
    WEnd
EndFunc   ;==>Example

I attached some screenshots to show what i say, Imagen1 is in windows 10 and Imagen2 in windows 7.

Sorry for my english, it's not my native lenguaje :/

Imagen1.png

Imagen2.png

Link to comment
Share on other sites

Very interesting.  I'm not an expert but I'd imagine it's a new feature in Windows 10 to convert an image file into a compatible graphic (bitmap?) for the RichEdit control.  I'd be interested if there is an easy way to tweak the control on Windows 7 to produce the same behavior.  

I assume you are looking to add an image to a GUI "at will" (during run-time).  If you don't need the fancy edit control like functionality (being able to type and paste data into the control) you could use alternative means to display the graphic (i.e. graphics control, GDI+).  Just wanted to offer alternatives and better understand what you are looking to accomplish.
 

Link to comment
Share on other sites

Thanks for your response, i need this to happen in run-time :/
I discovered that windows 8 have the same behavior that windows 10 (maybe you are right, and it's a new feature).
Also, if you open the image in paint, select it all, copy to the clipboard, and paste in the richedit, it will show the image (like windows 10), but in its real size (windows 8/10 resize it a little, see new screenshot)

Imagen3.png

Link to comment
Share on other sites

I'm on Windows 7 as well and get the icon when dropping the image. I converted the exact image to bmp (in paint) and it loaded it properly.

Only thing I can think of is intercept whatever windows message you're getting to load the picture and convert to a bmp before loading in richedit. Unfortunately, I don't know what the message is or how to load an image on richedit (I actually didn't even know richedit could do that! lol)

Link to comment
Share on other sites

I keep investigating, in https://msdn.microsoft.com/en-us/library/windows/desktop/bb774325(v=vs.85).aspx appears the definition of  __RichCom_Object_QueryAcceptData , but can't read the LPDATAOBJECT ($pDataobj), there should be the image binary (I think).

 

Also, I tried to put Win10/Office 2016 MSFTEDIT.DLL and RICHED20.DLL files in the script's dir, but I think the script doesn't recognize the files.
https://github.com/dpradov/keynote-nf/issues/530
http://www.kinook.com/Forum/showthread.php?t=2853

Edited by Gianfranco_753
More Info
Link to comment
Share on other sites

If someone need it, I made a workaround:

First, I add the following code the beginning of the project, before i created the GUICtrlRichEdit

Global $bAcceptData = False
If @OSBuild < 9600 Then ;If it's older than Windows 8
    ;Change the callback of the UDF to a new one
    Global $__g_pRichCom_Object_QueryAcceptData = DllCallbackRegister("__RichCom_Object_QueryAcceptDataWIN7", "long", "ptr;ptr;dword;dword;dword;ptr")
EndIf
;The new callback function
Func __RichCom_Object_QueryAcceptDataWIN7($pObject, $pDataobj, $pCfFormat, $vReco, $bReally, $hMetaPict)
    #forceref $pObject, $pDataobj, $pCfFormat, $vReco, $bReally, $hMetaPict
    If $bAcceptData Then
        Return $_GCR_S_OK ;Accept objects (and images)
    Else
        If Not $bReally Then MsgBox($MB_ICONWARNING,"", "If you wish to add an image on Windows 7 or older, you must do a right click and select add image.")
        Return $_GCR_E_INVALIDARG ;Don't add the object to the richedit.
    EndIf
EndFunc   ;==>__RichCom_Object_QueryAcceptData

Then created a context menu:

$Dummy1context = GUICtrlCreateContextMenu(GUICtrlCreateDummy())
$InsertarImagen = GUICtrlCreateMenuItem("Add image", $Dummy1context)
GUICtrlSetOnEvent($InsertarImagen, "InsertarImagenClick")
Func InsertarImagenClick()
    Local $sTipoImagen
    Local $sImagen = FileOpenDialog("Select the image that you want to add", @ScriptDir & "\", "Images (*.png;*.jpg;*.jpeg;*.bmp)", $FD_FILEMUSTEXIST)
    If Not @error Then
        Local $vClipBoardBackup = _ClipBoard_GetData()
        If _ClipBoard_Open($RegistroDiarioDeActividades) Then
            Local $fFactor = 0.5669 ;Or the image will be too big for my control
            _GDIPlus_Startup()
            Local $hImg2 = _GDIPlus_ImageLoadFromFile($sImagen)
            Local $iW = _GDIPlus_ImageGetWidth($hImg2)*$fFactor
            Local $iH = _GDIPlus_ImageGetHeight($hImg2)*$fFactor
            $hImg = _GDIPlus_ImageResize($hImg2, $iW, $iH)
            _GDIPlus_ImageDispose($hImg2)
            Local $hBitmap2 = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImg)
            Local $hBitmap = _WinAPI_CopyImage($hBitmap2,0,0,0,$LR_COPYDELETEORG+$LR_COPYRETURNORG)
            _WinAPI_DeleteObject($hBitmap2)
            _GDIPlus_ImageDispose($hImg)
            _GDIPlus_Shutdown()
            _ClipBoard_SetDataEx($hBitmap, $CF_BITMAP)
            _ClipBoard_Close()
            $bAcceptData = True
            Sleep(250)
            Send("^v")
            $bAcceptData = False
            _ClipBoard_SetData($vClipBoardBackup)
        Else
            MsgBox(0,'',"_ClipBoard_Open failed")
        EndIf
    EndIf
    FileChangeDir(@ScriptDir)
    Return True
EndFunc

And finaly, create the RichEdit and add

_GUICtrlRichEdit_SetEventMask($hRichEdit, $ENM_MOUSEEVENTS)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $wParam
    Local $hWndFrom, $iCode, $tNMHDR, $tMsgFilter, $hMenu
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hRichEdit
            Select
                Case $iCode = $EN_MSGFILTER
                    $tMsgFilter = DllStructCreate($tagMSGFILTER, $lParam)
                    If DllStructGetData($tMsgFilter, "msg") = $WM_RBUTTONUP Then
                        $hMenu = GUICtrlGetHandle($Dummy1context)
                        _GUICtrlMenu_TrackPopupMenu($hMenu, $hWnd)
                    EndIf
            EndSelect
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

That way, i can add images in all the systems (drag&drop in windows >= 8 and add with the button on windows < 8)

I hope this could help someone in the future.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...