Показать сообщение отдельно
  #3  
Старый 28.09.2017, 11:28
Shaft Shaft вне форума
Новичок
 
Регистрация: 15.05.2013
Сообщения: 74
Версия Delphi: 7/10.4
Репутация: 12
По умолчанию

Через ShellExecute у меня есть PinTo10v2, тоже работает. Но хочется все одним файлом. У меня есть исходник PinTo10v2 но она на C#
Вот как она это делает:

Код:
if (taskbar)
{ 
  Utils.ChangeImagePathName("explorer.exe");
  success = Utils.PinUnpinTaskbar(fileName, pin);
  if (success) Utils.RestoreImagePathName();
}
код PinUnpinTaskbar
Код:
public static bool PinUnpinTaskbar(string filePath, bool pin)
        {
            if (!System.IO.File.Exists(filePath))
            {
                Console.WriteLine("\n\r" + "Specified file not found.  Exiting...");
                Environment.Exit(1);
            };
            //throw new FileNotFoundException(filePath);
            int MAX_PATH = 255;
            var actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
            StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
            IntPtr hShell32 = LoadLibrary("Shell32.dll");
            LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
            string localizedVerb = szPinToStartLocalized.ToString();
            string path = Path.GetDirectoryName(filePath);
            string fileName = Path.GetFileName(filePath);
            // create the shell application object
            dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
            dynamic directory = shellApplication.NameSpace(path);
            dynamic link = directory.ParseName(fileName);
            dynamic verbs = link.Verbs();
            for (int i = 0; i < verbs.Count(); i++)
            {
                dynamic verb = verbs.Item(i);
                var name = verb.Name;
                //Console.WriteLine("Verb Name = " + name);
                if (verb.Name.Equals(localizedVerb))
                {
                    //Console.WriteLine("Trying to do it...");
                    verb.DoIt();
                    return true;
                }
            }
            return false;
        }
Код ChangeImagePathName
Код:
internal static void ChangeImagePathName(string newFileName)
        {
            IntPtr imageOffset, imageBuffer;
            GetPointers(out imageOffset, out imageBuffer);

            //Read original data
            var imageLen = Marshal.ReadInt16(imageOffset);
            originalImagePathName = Marshal.PtrToStringUni(imageBuffer, imageLen / 2);

            var newImagePathName = Path.Combine(Path.GetDirectoryName(originalImagePathName), newFileName);
            if (newImagePathName.Length > originalImagePathName.Length) throw new Exception("new ImagePathName cannot be longer than the original one");

            //Write the string, char by char
            var ptr = imageBuffer;
            foreach (var unicodeChar in newImagePathName)
            {
                Marshal.WriteInt16(ptr, unicodeChar);
                ptr = ptr.Increment(2);
            }
            Marshal.WriteInt16(ptr, 0);

            //Write the new length
            Marshal.WriteInt16(imageOffset, (short)(newImagePathName.Length * 2));
        }

PinUnpinTaskbar на Delphi будет как то так
Код:
const
    LOAD_LIBRARY_AS_DATAFILE = $2;

function LoadLibraryEx(lpFileName: String; hFile: THandle; dwFlags: DWORD): THandle; external 'LoadLibraryExA@kernel32.dll stdcall';
function LoadString(hInstance: THandle; uID: SmallInt; var lpBuffer: Byte; nBufferMax: Integer): Integer; external 'LoadStringA@user32.dll stdcall';

//
function PinToTaskbar(Filename: String): Boolean;
var
    hInst: THandle;
    buf: array [0..255] of byte;
    i: byte;
    strVerb, s: String;
    objShell, colverbs: Variant;
begin
    if not FileExists(Filename) then Exit;
    if (GetWindowsVersion shr 24 = 6) and ((GetWindowsVersion shr 16) and $FF = 1) then
    begin
        hInst := LoadLibraryEx(ExpandConstant('{sys}\shell32.dll'), 0, LOAD_LIBRARY_AS_DATAFILE);
        for i := 0 to LoadString(hInst, 5386, buf[0], 255)-1 do strVerb := strVerb + Chr(Buf[i]);
        FreeDLL(hInst);
        try
            objShell := CreateOleObject('Shell.Application');
        except
            ShowExceptionMessage;
            Exit;
        end;
        colVerbs := objShell.Namespace(ExtractFileDir(Filename)).ParseName(ExtractFileName(Filename)).Verbs;
        for i := colVerbs.Count downto 1 do if colVerbs.Item[i].Name = strVerb then
        begin
            colVerbs.Item[i].DoIt;
            Result := True;
        end;
    end;
end;
Но чет не пашет, почему то в colVerbs.Item[i].Name нет "Закрепить на панели задач", выводил в memo, все есть а этого нет, видимо ChangeImagePathName играет значительную роль, но я не знаю C# поэтому даже не могу определить что она делает
Ответить с цитированием