2009-07-17 6 views
1

J'ai une question liée à la gestion des objets OLE dans un RichTextBox. Ce que j'ai trouvé jusqu'à présent, c'est beaucoup d'infos, mais pas exactement ce dont j'ai besoin, donc je ferai une introduction rapide en premier (j'espère aussi que quelqu'un pourrait trouver cela utile).Suppression (ou mise à jour) d'une image de RichTextBox

1. Ce que je sais à ce jour

Tout d'abord, j'utilise OLE pour insérer des images (ou tout ActiveX) dans le RichTextBox. Ceci est censé être "la bonne manière" de le faire, car il n'y a pas de presse-papiers impliqué, et vous pouvez insérer n'importe quel contrôle ActiveX que vous voulez. Il y a un article sur CodeProject (MyExtRichTextBox) qui explique comment le faire (avec le code source complet), mais pour faire court:

En utilisant P/Invoke, la fonction OleCreateFromFile est importée de ole32.dll pour créer un OLE objet du fichier image.

int hresult = OleCreateFromFile(...); 

Fonction renvoie une instance IOleObject, qui doit alors être référencé par un struct REOBJECT:

REOBJECT reoObject = new REOBJECT(); 

reoObject.cp = 0; // charated index for insertion 
reoObject.clsid = guid; // iOleObject class guid 
reoObject.poleobj = Marshal.GetIUnknownForObject(pOleObject); // actual object 

// etc. (set other fields 

// Then we set the flags. We can, for example, make the image resizable 
// by adding a flag. I found this question to be asked frequently 
// (how to enable or disable image drag handles). 
reoObject.dwFlags = (uint) 
    (REOOBJECTFLAGS.REO_BELOWBASELINE | REOOBJECTFLAGS.REO_RESIZABLE); 

// and I use the `dwUser` property to set the object's unique id 
// (it's a 32-bit word, and it will be sufficient to identify it) 
reoObject.dwUser = id; 

Et enfin, la structure est passée à l'aide RichTextBox IRichEditOle.InsertObject. IRichEditOle est une interface COM, importée à l'aide de P/Invoke également. Le "id" pour l'objet me permet de parcourir la liste des objets insérés, et "faire des choses". En utilisant IRichEditOle.GetObject je peux obtenir chaque objet inséré et vérifier le champ dwUser pour voir si l'id correspondait.

2. Problèmes

Maintenant viennent les questions:

a) Le premier problème est mise à jour d'une image insérée. Je veux pouvoir "rafraîchir" certaines images à la demande (ou les changer). La façon dont je le fais est en ce moment quelque chose comme ceci:

if (reoObject.dwUser == id) 
{ 
    // get the char index for the "old" image 
    oldImageIndex = reoObject.cp; 

    // insert the new image (I added this overload for testing, 
    // it does the thing described above) 
    InsertImageFromFile(oldImageIndex, id, filename); 

    // and now I select the old image (which has now moved by one "character" 
    // position to the right), and delete it by setting the selection to "" 
    _richEdit.SelectionStart = oldImageIndex + 1; 
    _richEdit.SelectionLength = 1; 
    _richEdit.SelectedText = ""; 
} 

Depuis que je suis mise à jour du fil Gui, je crois que je ne devrais pas être inquiet sur l'utilisateur de changer la sélection au cours de cette méthode, car les blocs d'insertion OLE le fil, et l'application est en cours d'exécution en STA.

Mais je pense d'une manière ou d'une autre qu'il pourrait y avoir une meilleure façon de le faire? Cette méthode semble que je devrais le marquer avec un attribut [DirtyHack].

b) L'autre problème est que, au moment de l'insertion (IRichEditOle.InsertObject), j'obtiens une exception non gérée (Paint Shop Pro a cessé de fonctionner). Il semble que l'insertion de l'objet OLE démarre en quelque sorte cette application, bien qu'aucune association de fichier n'existe pour les commandes shell Ouvrir ou Modifier.

Est-ce que quelqu'un sait ce qui pourrait être à l'origine de ce problème et comment l'éviter?

[Modifier]

Je viens de recevoir une autre idée - je pourrais créer mon contrôle ActiveX qui prendrait soin de mettre à jour l'image.Dans ce cas, j'aurais seulement besoin d'invalider cette partie du RichTextBox (similaire à ce que fait l'auteur de l'article CodeProject). Mais cela rendrait le déploiement un peu plus compliqué (j'ai besoin d'exposer une classe .Net à COM, puis de l'enregistrer avant l'intégration).

Répondre

0

Je ne connais pas grand-chose à propos de .NET/OLE/ActiveX etc, mais lors de la programmation d'interfaces graphiques, vous devriez éviter de modifier/rafraîchir les fenêtres des threads.

J'ai eu des expériences similaires avec C++. Plutôt que d'utiliser un thread pour modifier votre fenêtre, vous devriez utiliser quelque chose comme une minuterie.

+1

Comme je l'ai dit, je suis mise à jour à partir du fil * Gui *. – Groo

Questions connexes