Search code examples
delphihierarchyskypewindow-handles

Detecting whether Skype is in "Compact View" or "Default View"


The way my application functions, is determined by Skype's view mode, due to the fact that my application is looking for windows of class TConversationWindow, which if in Default View is a child of tSkMainForm, and if in Compact View, it is not a child of tSkMainForm.

Here is what I tried to do:

Function IsCompactView:Boolean;
Var
 Wnd : Hwnd;
Begin
  Result := True;
  Wnd := FindWindow('TConversationForm',nil);

  if Wnd <> 0 then
  begin
   Wnd := GetParent(Wnd);
   // Custom function that grabs the Window Text
   if GetHandleText(Wnd) <> '' then
   Result := False;

  end;

End;

The above function will look for top-level (unless I am mistaken - the windows with no window parent) TConversationForm's, by checking if their parent has text or not. If Skype is in Default View, the TConversationForm's are children of tSkMainForm, which always has some text. It works as it is supposed to.

Now for the actual problem: Whenever the user switches between the 2 views, the top-level TConversationForm's are not "refreshed". They disappear alright, but in order for it to appear as a child of tSkMainForm again (so the change is visible in Winspector Spy), you have to select it in Skype, and I cannot rely on the user to do that.

In case you dont know, here is the difference between the 2 views:

Compact View

Compact View

Default View

Default View

If you need more info please let me know, thanks!


Solution

  • Instead of detect if Skype is in “Compact View” or “Default View” using a windows approach try reading the config.xml file which store these kind of settings and is updated in "real-time" by skype. This file is located in

    %AppData%\Skype\<your-skype-user-name>
    

    for example in windows 7 this is the location

    C:\Users\<your windows user>\AppData\Roaming\Skype\<your-skype-user-name>
    

    Inside of this file in the exist a entry called MultiWindowMode

    This is the Xpath location of the MultiWindowMode

    /config/UI/General/MultiWindowMode'
    

    The value of this entry is '1' for “Compact View” and '0' for “Default View”

    Check this demo which uses XPath to parse the file and read the value of the MultiWindowMode.

    {$APPTYPE CONSOLE}
    
    uses
      ComObj,
      ActiveX,
      Variants,
      SysUtils;
    
    
    function SkypeISCompactView(const SettingsFile : string) : Boolean;
    var
       XmlDoc      : OleVariant;
       Node        : OleVariant;
    begin
      Result:=False;
       if FileExists(SettingsFile) then
       begin
         XmlDoc       := CreateOleObject('Msxml2.DOMDocument.6.0');
         try
           XmlDoc.Async := False;
           XmlDoc.Load(SettingsFile);
           XmlDoc.SetProperty('SelectionLanguage','XPath');
    
            if (XmlDoc.parseError.errorCode <> 0) then
             raise Exception.CreateFmt('Error in Xml Data %s',[XmlDoc.parseError]);
    
           Node  :=XmlDoc.selectSingleNode('/config/UI/General/MultiWindowMode');
           if not VarIsClear(Node) then
            Result:=Node.text='1';
         finally
           XmlDoc:=Unassigned;
         end;
       end;
    end;
    
    
    begin
     try
        CoInitialize(nil);
        try
          Writeln(BoolToStr(SkypeISCompactView('C:\Users\<your windows user>\AppData\Roaming\Skype\<skype user>\config.xml'),True));
        except
          on E:Exception do
          begin
              Writeln(E.Classname, ':', E.Message);
          end;
        end;
     finally
          CoUninitialize;
     end;
     Readln;
    end.