Через 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# поэтому даже не могу определить что она делает