Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   IPictureDisp al portapapeles (https://www.clubdelphi.com/foros/showthread.php?t=87603)

aguml 29-01-2015 17:49:34

IPictureDisp al portapapeles
 
Pues siguiendo la ayuda del componente que estoy probando veo que para guardar una imagen de lo que se muestra al portapapeles hace esto:

Código:

' Copy the diagram to the clipboard:
' here we wish to copy all items and the back picture.
Clipboard.Clear
Clipboard.SetData
AddFlow1.ExportPicture(afAllItems, False, True)

ExportPicture devuelve un IPictureDisp**.
El problema es que eso es VB y que no se como pasarlo a C++builder ¿alguien sabria decirme como hacer eso?

aguml 29-01-2015 19:42:48

He probado a hacer cosas como estas que pongo a continuacion pero nada me funcionó :(

Código PHP:

void __fastcall TForm1::Exportarimagendeseleccionadosalportapapeles1Click(
      
TObject *Sender)
{
   
Clipboard()->Open();
   
Clipboard()->Clear();
   
TPicture *pIPD = new TPicture;
   
pIPD->Assign((TPersistent*)AddFlow1->ExportPicture(afSelectedItemstruetrue));
   
Clipboard()->SetAsHandle(CF_METAFILEPICTpIPD->Metafile->Handle);
   
Clipboard()->Close();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ExportarImagendetodosalportapapeles1Click(
      
TObject *Sender)
{
   
Clipboard()->Open();
   
Clipboard()->Clear();
   
IPictureDisp **pIPD AddFlow1->ExportPicture(afAllItemstruetrue);
   
Clipboard()->SetAsHandle(CF_METAFILEPICT, (unsigned int)pIPD);
   
Clipboard()->Close();



aguml 31-01-2015 13:47:22

Sigo investigando como conseguirlo y he llegado a esto:
Código PHP:

unsigned int DataHandle;
HPALETTE APalette;
unsigned short MyFormat;
TPicture *pic;
IPictureDisp **pIPD;

//Obtengo el puntero al IPictureDisp
pIPD AddFlow1->ExportPicture(afAllItemstruetrue);

try
{
   
pic = new TPicture//Solicito memoria para el TPicture
   
__try
   
{
      try
      {
         
SetOlePicture(pic, *pIPD); //Paso la imagen del IPictureDisp al TPicture

         //Envio la imagen al portapapeles
         
pic->SaveToClipboardFormat(MyFormat,DataHandle,APalette);
         
Clipboard()->SetAsHandle(MyFormat,DataHandle);
      }catch(...){
         
ShowMessage("Fallo al copiar la imagen al portapapeles.");
      }
   }
__finally{
      
delete pic//Libero la memoria del TPicture
   
}
}catch(...){
   
ShowMessage("No hay memoria suficiente.");


Cuando llego aquí da una excepcion:
Código PHP:

SetOlePicture(pic, *pIPD); 

Si entro con F7 veo esto:
Código PHP:

__fastcall DelphiInterface<T>(Trhs)
{
   if (
rhs != 0)
     
rhs->AddRef();
   
intf rhs;


Si voy linea a linea veo que al intentar ejecutar rhs->AddRef(); ese metodo no existe para ese objeto.
He mirado con OleViewer y no veo el interface IPictureDisp por ningun sitio pero si veo IPicture ¿como puede ser que no aparezca entre las interfaces y builder lo reconozca? ¿que puedo estar haciendo mal para que no funcione mi codigo?

aguml 01-02-2015 18:25:47

Amigo, si hago esto:

IPictureDisp *pIPD = AddFlow1->ExportPicture(afAllItems, true, true);

Me da este error al compilar:

[C++ Error] Main.cpp(731): E2034 Cannot convert 'IPictureDisp * *' to 'IPictureDisp *'


La ayuda del componente no da mucha ayuda ya que casi todo el soporte lo da para VB y en algun que otro caso pone algun ejemplo en C++. Aqui los tres ejemplos que pone para ese metodo en VB:

Export the diagram to a picture box:

Código PHP:

' here, we copy only the selected items.

Picture1.Picture = AddFlow1.ExportPicture(afSelectedItems, False, False)
 


Example 2 (VB)


Código PHP:

' Copy the diagram to the clipboard:

here we wish to copy all items and the back picture.&#8233;
Clipboard.Clear&#8233;
Clipboard.SetData AddFlow1.ExportPicture(afAllItemsFalseTrue)&#8233; 

Example 3 (VB)


Código PHP:

' Save the diagram in a file:

here we don&#8250;t want to save the grid.

Dim pic As IpictureDisp&#8233;
AddFlow1.ShowGrid False&#8233;
Set pic AddFlow1.ExportPicture(afAllItemsTrueTrue) &#8233;
AddFlow1.ShowGrid True&#8233;
SavePicture pic"myfile.emf"&#8233;
 


Traceando puedo ver que ExportPicture se declara asi:

Código PHP:

IPictureDisp** __fastcall TAddFlow::ExportPicture(Addflow5lib_tlb::ItemSetConstants ItemSet, &#8233; VARIANT_BOOL IncludeBackColor,
 VARIANT_BOOL IncludeBackPic)
{

return GetDefaultInterface()->ExportPicture(ItemSetIncludeBackColorIncludeBackPic);&#8233;




Si entro con F7 llego aqui:

Código PHP:

IPictureDisp** __fastcall ExportPicture(Addflow5lib_tlb::ItemSetConstants ItemSet, &#8233; VARIANT_BOOL IncludeBackColor, VARIANT_BOOL IncludeBackPic)

 
{
 
_TDispID _dispid(/* ExportPicture */ DISPID(134));&#8233; 
TAutoArgs<3_args;&#8233;
 
_args[1] = (int)ItemSet /*[VT_USERDEFINED:0]*/;&#8233;
 
_args[2] = IncludeBackColor /*[VT_BOOL:0]*/;&#8233;
 
_args[3] = IncludeBackPic /*[VT_BOOL:0]*/;&#8233;
 
OleFunction(_dispid_args);&#8233;
 
return (IPictureDisp** /*[C1]*/)(LPDISPATCH/*[VT_DISPATCH:1]*/_args.GetRetVariant();
}&
#8233; 

He traceado por dentro y no veo que en ningun sitio llame a Release() y ya no se que mas puedo probar. 


aguml 01-02-2015 23:05:52

Por favor, que algun administrador elimine la respuesta anterior ya que el formato no está bien. Aqui lo pongo bien:

Amigos, si hago esto:
Código PHP:

IPictureDisp *pIPD AddFlow1->ExportPicture(afAllItemstruetrue); 

Me da este error al compilar:
Código:

[C++ Error] Main.cpp(731): E2034 Cannot convert 'IPictureDisp * *' to 'IPictureDisp *'
La ayuda del componente no da mucha ayuda ya que casi todo el soporte lo da para VB y en algun que otro caso pone algun ejemplo en C++. Aqui los tres ejemplos que pone para ese metodo en VB:

Example 1 (VB)
Código:

' Export the diagram to a picture box:
' here, we copy only the selected items.
Picture1.Picture = AddFlow1.ExportPicture(afSelectedItems, False, False)

Example 2 (VB)
Código:

' Copy the diagram to the clipboard:
' here we wish to copy all items and the back picture.
Clipboard.Clear
Clipboard.SetData AddFlow1.ExportPicture(afAllItems, False, True)

Example 3 (VB)
Código:

' Save the diagram in a file:
' here we don›t want to save the grid.
Dim pic As IpictureDisp
AddFlow1.ShowGrid = False
Set pic = AddFlow1.ExportPicture(afAllItems, True, True)
AddFlow1.ShowGrid = True
SavePicture pic, "myfile.emf"

Traceando puedo ver que ExportPicture se declara asi:
Código PHP:

IPictureDisp** __fastcall TAddFlow::ExportPicture(Addflow5lib_tlb::ItemSetConstants ItemSet,
                                                                      
VARIANT_BOOL IncludeBackColor,
                                                                      
VARIANT_BOOL IncludeBackPic)
{
  return 
GetDefaultInterface()->ExportPicture(ItemSetIncludeBackColorIncludeBackPic)


Si entro con F7 llego aqui:
Código PHP:

IPictureDisp** __fastcall ExportPicture(Addflow5lib_tlb::ItemSetConstants ItemSet,
                                                 
VARIANT_BOOL IncludeBackColor,
                                                     
VARIANT_BOOL IncludeBackPic)
{
    
_TDispID _dispid(/* ExportPicture */ DISPID(134));
    
TAutoArgs<3_args;
    
_args[1] = (int)ItemSet /*[VT_USERDEFINED:0]*/;
    
_args[2] = IncludeBackColor /*[VT_BOOL:0]*/;
    
_args[3] = IncludeBackPic /*[VT_BOOL:0]*/;
    
OleFunction(_dispid_args);
    return (
IPictureDisp** /*[C1]*/)(LPDISPATCH/*[VT_DISPATCH:1]*/_args.GetRetVariant();


He traceado por dentro y no veo que en ningun sitio llame a Release() y ya no se que mas puedo probar.

aguml 02-02-2015 13:04:58

He hecho una prueba para intentar ver que pasa:
Código PHP:

   unsigned int DataHandle;
   
HPALETTE APalette;
   
unsigned short MyFormat;
   
TPicture *pic;
   
IPictureDisp *pIPD;

   
//Obtengo el puntero al IPictureDisp
   
pIPD = (IPictureDisp*)AddFlow1->ExportPicture(afAllItemstruetrue);

   try
   {
      
pic = new TPicture//Solicito memoria para el TPicture

      
__try
      
{
         try
         {
            
//Prueba que deberia pasar la imagen al IPictureDisp
            
pic->LoadFromFile("Diagramas.wmf"); //Leo una imagen desde un archivo
            
GetOlePicture(picpIPD); //La paso del TPicture al IPictureDisp
            
SetOlePicture(picpIPD); //La paso del IPictureDisp al TPicture

            //Envio la imagen al portapapeles
            
pic->SaveToClipboardFormat(MyFormat,DataHandle,APalette);
            
Clipboard()->SetAsHandle(MyFormat,DataHandle);
         }catch(...){
            
ShowMessage("Fallo al copiar la imagen al portapapeles.");
         }
      }
__finally{
         
delete pic//Libero la memoria del TPicture
      
}
   }catch(...){
      
ShowMessage("No hay memoria suficiente.");
   } 

Lo que hago es leer una imagen desde el TPicture, luego la paso al IPictureDispatch y luego la vuelvo a pasar al TPicture desde el IPictureDisp. Pues bien:
1- Al IPictureDisp le tengo que hacer un cast mas que extraño al asignarlo para que no de error despues.
2- Tanto GetOlePicture como GetOlePicture devuelven void por lo que no se si fallan pero no dan excepcion ninguna.
3- Cuando uso GetOlePicture no veo que nada cambie en el IPictureDisp.
4- Cuando uso SetOlePicture puedo ver como cambia el valor de FGrafic en su interior.

¿como puede ser que solo con copiar la imagen de uno a otro y luego otra vez volver a hacer lo mismo ya no sea capaz de leer la imagen? Creo que GetOlePicture no hace lo que debe o que IPictureDisp no se inicializa como debe. ¿Alguien puede ayudarme?

ecfisa 02-02-2015 13:23:01

Hola aguml.

No quiero que te quedes con la idea de que no hay voluntad de ayudarte. En mi caso (y creo que en el de todos los que han leido el hilo) el mutismo se debe al desconocimiento sobre IPictureDisp.

Fijate si este enlace te puede arrojar algo de luz: Converting between IPictureDisp and System.Drawing.Image

Saludos :)

aguml 02-02-2015 16:25:26

amigo en ningun caso pensé en que no hubiese voluntad de ayudar, entiendo que unos por falta de tiempo, otros por desconocimiento, y otros por otras razones, pues no ha podido ser y por eso sigo investigando y probando por mi cuenta y compartiendo mis pruebas para ver si alguien que pueda me ayuda. El enlace que indindicas ya lo vi pero usa stdole y no se como hacer para que el builder me lo reconozca ya que no comila con eso.


La franja horaria es GMT +2. Ahora son las 15:05:05.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi