Thursday, December 16, 2004

Adobe SDK - plugin conflict

I had a problem with an InDesign plugin I was developing lately, the problem occours when you run InDesign and InDesign tell you that the plugin will conflicts with itself.
After a lot of tries (the plugin was pretty empty) I found out that the problem was a command that was something like:

IID_ICOMMAND, kSampleCmdImpl,

The culprit is the IID_ISAMPLENAMEDATA, it seems like a commands cannot have two standard kStringDataImpl, so the solution is to replace the second kStringDataImpl, to do this we need to simply define an implementation alias like this:

resource ImplementationAlias(1)
kSampleNameDataImpl, kStringDataImpl,

so now we can modify our command in this way:

IID_ICOMMAND, kSampleCmdImpl,

and don't forget to add the kSampleNameDataImpl implementation if the xxxID.h

Friday, November 19, 2004


If you are compiling a custom widget that derives from CControlView and the linker fails saying that it cannot find some methods of CControlView, it is high probable that you have remove NO_STRICT from the project preprocessor options.

Wednesday, September 15, 2004

How to import an Image with InCopy

Just look at the InDesign knowledge base (

Hint: use the stream Luke.

Monday, August 02, 2004

Last night I didn't sleep to it is a photo of the moon shooted at 4am. Posted by Hello

Monday, July 26, 2004

Me anche Chiara having fun in Stresa Posted by Hello

Wednesday, July 07, 2004

Indesign SDK

I was trying to understand how to catch a menu action for a standard Indesign menu item. Looking trough the indesign forum I found out a couple of messages that points to the knowledge base, in particular to "How To: Intercept the File>Open menu event" and "How To: Get the filename from File>New or File>Open menu dialogs".

Adobe Indesign web pages

There are some really useful pages in the adobe web site regarding incopy/indesign development:

Indesign Developer Knowledgebase

Indesign user to user forum


Tuesday, July 06, 2004


I found out this site that contains a lot of useful information for who cooks rarely (like me).

Friday, July 02, 2004

Indesign SDK - plugin ID

Don't forget to register you plugin with Adobe in order to have an unique Plugin ID. Adobe provided an How to explaining all the necessary steps. The registration page is here.

Thursday, July 01, 2004

Indesign SDK - Front Document

When you want to obtain a pointer to the current front document (the one the user is editing) you could use

InterfacePtr doc(Utils()->GetFrontDocument(), UseDefaultIID());
but when you are inside an action component it may not work, instead you should use
InterfacePtr doc(ac->GetContextDocument(), UseDefaultIID());
where ac is the IActiveContext* passed in the DoAction.

Thursday, June 24, 2004

Source code mismatch during debugging

When you are debugging an application, if the source executed by the debugger is different than the actual source code (i.e. the code executed is not the code showed in the source code) and you are sure the pdb is absolutely right for that dll/exe, it means one of these 2 things:

1. your source code is not up to date;

2. you may have non-dos line ending mixed in the file.

I did have this problem in the past days with code I've written pretty much from scratch, it turned up to be case number 2. Probably I copy-pasted a small portion from a mac code. A full conversion to DOS endings of the source file solved the problem. I was plagued by it since two weeks ago, but only in two files, that I didn't change very much in the last days, so I let the problem remain, but today I decided I had to solve the problem because there weren't any reasonable explanation of this weird problem. Fortunately I had the idea of checking the line endings of the file and that solved my problems.

Thursday, June 17, 2004

Indesign SDK - Query story metadata

How to query for story's metadata?

Simple, assuming storyRef is the UIDRef of the story:

    Utils inCopyWorkFlowUtils;

InterfacePtr model(storyRef, IID_ITEXTMODEL);
InterfacePtr iMetaData(inCopyWorkFlowUtils->QueryTextMetaDataBoss(model, kTrue));
if (iMetaData) {
InterfacePtr mdAcc(iMetaData, UseDefaultIID());
if (mdAcc) {
InterfacePtr mdPaths(mdAcc->Enumerate(0));
if (mdPaths) {
// iterate thru all paths
while (mdPaths->HasMorePaths()) {
PMString nspace, path;
// get the next path (by namespace and path)
mdPaths->GetNextPath(nspace, path);
PMString value;
MetaDataFeatures metaDataFeatures;
// inspect the node
if (mdAcc->Get(nspace, path, value, metaDataFeatures))


Wednesday, June 09, 2004

Indesign menus

It took me a while to figure it out how to add a submenu in the main File menu and position it whereever I want. The solution came from a Ken Sadahiro answer to a forum post, which point out to a Q & A session (login ASN web account required) on user interface.

I tried to do something similar, but the culprit is the 0 as the actionID for the sub-menu and the use of the delimiter ":" when adding the submenu.

Tuesday, June 08, 2004


I used to work for Tera until March 2003, recently I discovered a guy, Derek Lakin, who worked for NEP.

Nep (or I should say Nep's "this is" project) is a fantastic project that delivers all the regional news trough one big site, I was in charge of the part of the project that allow to transfer editorial content (pics and stories) from the editorial system to Nep's CMS.

Tuesday, June 01, 2004

Indesign SDK - custom draw palette

Indesign doesn't use windows to put together many panels into a palette or to draw the tab of a palette. It uses GDI (or the equivalent on the Mac) to draw everything on screen. IControlView is the interface for a "control", you can navigate the controls tree trough IWidgetParent interface (and GetParent method) and IPanelControlData or IPaletteControlData.

Suppose you have a panel that is subclassed by you, you can ask for the IPaletteControlData, this way:

IPaletteControlData* ppcd = nil;

InterfacePtr<IWidgetParent> parent(this, UseDefaultIID());

if( parent ) {

ppcd = static_cast<IPaletteControlData*>(parent->QueryParentFor(IID_IPALETTECONTROLDATA));


InterfacePtr<IPaletteControlData> pcd(ppcd);


Now you can use GetSectionCount and GetSection to retrieve the interface for the wanted control, the first one is the tab, the other is the entire panel. Suppose you want to enumerate the tabs in the palette, you need the PanelControlData for the tabs so:

InterfacePtr<IControlView> tabAreaView(pcd->GetSection(0), UseDefaultIID());


InterfacePtr<IPanelControlData> tabAreaCD(tabAreaView, UseDefaultIID());



for(int32 idx = 0; idx < tabAreaCD->Length(); idx++) {

InterfacePtr<IControlView> tabWidget(tabAreaCD->GetWidget(idx), UseDefaultIID());


And there you can draw whatever you want on the tab.

Wednesday, May 26, 2004

Indesign strikes back

This is related to incopy but I think indesign will behave the same because the plugins are cross-application ('till a certain point. i.e. you use specific custom functions).

The problem is another interface leak. The culprit is IWidgetUtils->QueryRelatedWidget, the documentation doesn't say anything particular about it but it looks to me that this method is returning an interface with the reference counter incremented.

I tried to look at the adobe samples but it is never used so I cannot say if I'm doing it wrong or the documentation (both help files and include files) is wrong. Anyway using the static_cast trick explained before solved my problem.

Pay attention to those leaks as soon as you got it, or you will have hard days finding the guilty.

InDesign newbiee problems

I was having an interface leak with InDesign, such leak caused all sort of others leaks that they had the potential to drive me to look at others places, fortunately I've got quite a lot experience with COM interface leaks.

After all the suspecting function was this one:

IPMUnknown* getPanelView(){

InterfacePtr parent(this, UseDefaultIID());
if( parent ) {
InterfacePtr parentPanel(parent->GetParent(), UseDefaultIID());
if( parentPanel )
return parentPanel->QueryParentFor(IID_ICONTROLVIEW);
return nil;
} // getPanelView

In particular I was using such function with an InterfacePtr like this:

InterfacePtr<IControlView> panel(getPanelView(), UseDefaultIID());

However if you look at the include file for IWidgetParent, you will find that QueryParentFor will return a reference incremented ptr to interface this means I will leak a reference to that interface. InterfacePtr have a constructor that doesn't call AddRef on the interface and it's the one that didn't do the QueryInterface. So the correct InterfacePtr is:

InterfacePtr<IControlView> panel(getPanelView());

But getPanelView must return an IControlView* or we should cast it here, I prefer the first solution, so I'll have:

IControlView* getPanelView(){

InterfacePtr parent(this, UseDefaultIID());
if( parent ) {
InterfacePtr parentPanel(parent->GetParent(), UseDefaultIID());
if( parentPanel )
return static_cast<IControlView*>(parentPanel->QueryParentFor(IID_ICONTROLVIEW));
return nil;
} // getPanelView

Moral of the story: read carefully documentation *and* include files before using any complex sdk.

Friday, May 21, 2004

incredible video

A friend of mine sent me a link to this really funny video I can't understand what they say but it is really really funny.

Indesign UI

If you are developing a dynamic palette in which you want to host a custom panel, you must be sure that the WidgetID that you will set for the panel must not clash with any of the IDs defined elsewhere.

If they clash you will have some really strange behaviour, for example I aggregated a simple interface to the panel (interface that will give me access to panel's options) but when I assign a conflicting widgetID everyone seems to work except the aggregated interface was not created at all.

I'm not that took me a couple of days to figure it out.

Monday, May 03, 2004

PNG in Windows IE

PNG in Windows IE


How to solve the PNG transparency problem with Ie 5.5 and 6.

Thursday, April 22, 2004


I was porting some code from vc6 to vc7.1 and I got stuck in:


c:\build\main\.......\inc.h(27) : fatal error C1001: INTERNAL COMPILER ERROR

(compiler file 'msc1.cpp', line 2701)

Please choose the Technical Support command on the Visual C++

Help menu, or open the Technical Support help file for more information


Looking trough newsgroups gave me a good hint:

"I spoke with Microsoft incident support for my MSDN licence and the fix is:

#if _MFC_VER < 0x0700
class CString;

CString is not a class in MFC anymore. It is a template in ATL so forward
declarations are invalid."

So I searched for CString forward declarations and I solved - quickly - my problem.

Tuesday, April 20, 2004


PINVOKE.NET attempts to address the difficulty of calling Win32 or other unmanaged APIs in managed code (languages such as C# and VB .NET).   Manually defining and using PInvoke signatures (also known as Declare statements in VB .NET) is an error-prone process that can introduce extremely subtle bugs.  The rules are complex, and if you make a mistake, you’ll probably corrupt memory.

 Therefore, this site is a repository where you can find, edit, and add PInvoke signatures, user-defined types, and any other information that helps us leverage each other’s efforts.  Think of this as the 21st century version of VB6’s "API Text Viewer," a standalone application which used static files such as WIN32API.TXT as input.  Did you spend hours figuring out how to successfully define & call a given unmanaged API in managed code?  Share (and get credit for) your discovery here!  Is there an error on this site?  Go ahead and fix it!


Tuesday, April 13, 2004

Monday, March 22, 2004

Visited Countries

This is the map of visited country 'till now.

Visited countries map


Look at this to create your own visited country map.

Thursday, March 04, 2004

Windows Forms FAQ

Windows Forms FAQ

the complete FAQ for c# newbies.

Tuesday, March 02, 2004

How to enable sound on a Virtual PC running Linux

Configure Sound in Red Hat Linux
1. Log into Red Hat Linux.
2. Start a terminal session, click the ‘Red Hat’, System Tools, then Terminal.
3. Type su and press Enter.
4. Enter the root password and press Enter.
5. Type cd /sbin and press Enter
6. Type ./sndconfig and press Enter.
7. Introduction: Press Enter.
8. Probe Results: Press Enter.
9. Card Type: Select Sound Blaster 16 and press Enter.
10. Card Settings:
a. I/O Port: Select 0x220 and press Tab.
b. IRQ: Select 5 and press Tab.
c. DMA 1: Select 1 and press Tab.
d. DMA 2: Select 5 and press Tab.
e. MPU I/O: Select 0x330 and press Tab.
f. Press Enter
11. Sound Card Test: Press Enter
NOTE Sound volume may be very low, adjust speakers accordingly.
12. Test Result: Press Enter if sound was heard, if not, Tab to select No and press Enter.
NOTE If no sound was heard, the most likely cause is lack of volume
13. File Exists: press Enter to overwrite the existing config file.
14. Type exit and press Enter to exit the root console.
15. Type exit and press Enter to exit the standard console.

Wednesday, February 18, 2004

Unicode question

A couple of days ago I wrote a simple function and a part of it looked like this:

CString str;
str.Format(_T("this is only a test"));
int idx = str.Find('o');
if( idx >= 0 )
str = str.Left(idx);

The project have UNICODE defined so when today I reviewed this piece of code it looked wrong because the Find method as a character parameter that is not treated really as an unicode character. However it did compile well (and work too) under Visual C++ 6.

So when I got home I decided I need to understand why it works. I opened my Microsoft Visual C++ .NET 2003 wrote this little test console app and I generated the asm and the results (in debug configuration) are:


; 22   :     int idx = str.Find('o');

mov esi, esp
push 0
push 111 ; 0000006fH
lea ecx, DWORD PTR _str$[ebp]
call DWORD PTR __imp_?Find@?$CStringT@GV? (...)
cmp esi, esp
call __RTC_CheckEsp
mov DWORD PTR _idx$[ebp], eax
; 22   :     int idx = str.Find(_T('o'));

mov esi, esp
push 0
push 111 ; 0000006fH
lea ecx, DWORD PTR _str$[ebp]
call DWORD PTR __imp_?Find@?$CStringT@GV? (...)
cmp esi, esp
call __RTC_CheckEsp
mov DWORD PTR _idx$[ebp], eax

So both of them are compiled in the same manner. That's explain why it did compile successfully and why it works but I still doesn't understand why it didn't require the L (or TEXT or _T) macro.

Tuesday, February 17, 2004

MFC and taskbar

To make your application to not have a taskbar button, you need to have you main window owned by an invisible window or the main window should have the WS_EX_TOOLWINDOW style.

Friday, February 13, 2004


When you are writing COM objects with support for OLE Automation types, you may have to deal with VARIANT_BOOL types. They are boolean values but unlink BOOL and bool its legal values are -1 (VARIANT_TRUE) and 0 (VARIANT_FALSE).

That means that if you call by mistake one of those methode with a bool or BOOL value, it will be implicitily converted to 0 and 1 values making it a perfectly legal call, but if you do have something like:


HRESULT foocall(VARIANT_BOOL boolParam)


    if( boolParam == VARIANT_TRUE )

        return S_OK;

    return S_FALSE;



Than you are in big trouble if you mismatch what you pass to the method. When you are dealing with VARIANT_BOOL types is always better to check for VARIANT_FALSE which is always 0 as for bool and BOOL types, so you should write the previous method like:


HRESULT foocall(VARIANT_BOOL boolParam)


    if( boolParam == VARIANT_FALSE )

        return S_FALSE;

    return S_OK;



Microsoft Win32 to Microsoft .NET Framework API Map

This link is something really useful for who is learning .net and have a tough win32 background.


Wednesday, February 11, 2004

The Ten Rules of Performance

From Paul Vick the 10 rules to work out perfomances problem:

I like the 9th and 10th rule, they are so true.

Monday, February 09, 2004

Callbacks in C++

While reading Raymond Chen today I came across a technique to implement callback in c++. Having already implemented such things on my own, I'll give it a try and eventually update my code.

Thursday, February 05, 2004

Goggle's power

Don Box was having problems looking up SOAP 1.1 protocol specs.

A simple google query would have give him the needed help.

Friday, January 30, 2004


From Eric Sink's blog:

"One of the toughest parts of cross-platform development is the build system.  No matter how clean and portable your C code is, getting the tree to build on multiple platforms is a whole different problem.

One solution I have used in the past is to do a completely Unix-centric build system with bash and make, using cygwin to run it under Windows.  This works very well, except that it really annoys the folks who prefer Visual Studio project files.


This week I discovered a nifty tool I had never seen before.  It's called CMake, and it's the build system used for Kitware's Visualization Toolkit.  I've seen lots of alternatives to 'make', but this tool is surprisingly different and deeply neato."


Tuesday, January 27, 2004

Thursday, January 08, 2004

Sviluppare senza essere Amministratori della macchina

From Marco Russo's blog:

Molti blog (tra cui quello di Paolo) hanno già notificato questo documento su MSDN che riassume gli interventi da fare per sviluppare senza essere amministratori.
Dopo 6 mesi di questa esperienza quello che posso dire è che la cosa più difficile, in realtà, non è sviluppare ma essere utenti "avanzati". Quello che nessuno spiega, infatti, è come far funzionare quelle centinaia di programmi e utility che vogliamo installare sul PC che usiamo tutti i giorni anche per lavorare.
Per venirne a capo, esistono due tool assolutamente indispensabili e di cui non posso più fare a meno: FileMon e RegMon.
Quando un programma non vuol saperne di funzionare senza avere un utente amministratore, in genere i problemi sono:
  • apre dei file di configurazione in read/write anche se deve solo leggerli, e questi file sono nella directory di installazione del programma (sotto Programmi/Program Files, che per un utente normale è tutta read-only) - con FileMon si capisce quale file tenta di aprire (fallendo) e quindi, modificando i diritti di accesso su tale file, si risolve il problema
  • apre una chiave di registry all'interno di HKEY_LOCAL_MACHINE in read/write, quando deve solo leggere (le scritture, al di fuori dell'installazione, andrebbero fatte sempre e solo su HKEY_CURRENT_USER) - con RegMon si individua il problema e... se si riesce, si modificano gli accessi al registry (usare REGEDT32.EXE su Windows 2000, da Windows XP in poi è tutto integrato in REGEDIT.EXE)
  • tenta di aprire in scrittura qualcosa nelle directory di sistema di Windows: qui è meglio sbarazzarsi del software e trovarne uno scritto meglio...
  • registrano dei componenti COM/ActiveX a ogni avvio dell'applicazione: anche qui insultate i programmatori... perché questo comportamento non dovrebbe essere ammissibile al di fuori dell'attività di setup - non ci sono grandi soluzioni se non eseguire tali programmi con RunAs...
A parte questi inconvenienti, sviluppare con un utente che non è amministratore è non solo possibile ma addirittura vantaggioso, perché consente di avere coscienza di cosa un programma deve fare e cosa no... prima che ve lo dica qualche utente/amministratore di rete un po' arrabbiato...
[Marco Russo's BLog]