标签: pinvoke

隐藏另一个应用的任务栏按钮

我希望能够从任务栏隐藏另一个应用程序的窗口,而不隐藏窗口本身.具体来说,我希望在Alt + Tab列表中运行,可见,可用的几个不同的Web浏览器,但不占用任务栏上的空间.

(如果有人好奇为什么:我编写了一个仪表板应用程序,它使用Vista的DwmRegisterThumbnail API同时显示几个窗口的实时预览 - 如果你愿意的话,这是一种"画中画".此时,还有任务栏按钮对于那些窗口似乎是多余的.)

我知道将其他窗口的样式更改为include WS_EX_TOOLWINDOW会将其隐藏在任务栏中,我先尝试了.但是,正如预期的那样,它有一些我不想要的副作用:标题栏变得更短(不是很糟糕,我猜)并且最小化和最大化按钮消失了(不好).我还必须隐藏并重新显示窗口以使任务栏识别出更改,这会导致重新绘制工件,当我对IE窗口进行操作时.

我的下一个想法是,由于默认情况下窗口与所有者隐藏在任务栏中,也许我可以将其他窗口更改为我的所有权.但MSDN 非常清楚 "创建一个拥有的窗口,应用程序无法将窗口的所有权转移到另一个窗口."

我发现这个问题与我的问题类似,但它特别关注来自您自己的进程的窗口,您可以完全控制窗口所有权.

有没有人知道隐藏任务栏按钮的任何其他方法,这将适用于来自另一个进程的窗口?


更新: Tormod通过ITaskbarList让我走上正轨 - 它运行良好.pinvoke.net页面有一些错误(错误的GUID,按字母顺序而不是按接口顺序声明的方法),但我编辑了它,进行了更正,还添加了一个如何通过其coclass实例化ITaskbarList的示例.

更新2:如果您使用DeleteTab隐藏窗口的任务栏按钮,然后将其设置为活动窗口(例如,通过SetForegroundWindow或Alt + Tab),它的任务栏按钮将重新出现.为了保持任务栏按钮隐藏,我不得不添加一个计时器并继续调用DeleteTab.只要您不介意任务栏按钮在窗口聚焦时重新出现,这很有效.

.net c# pinvoke

14
推荐指数
1
解决办法
4039
查看次数

将ISO C++类暴露给C#

我需要向C#公开一些C++类(我在Linux上构建,使用单声道,所以COM不是一个选项)

到目前为止我收集的证据表明,解决这个问题的最佳方法是:

  1. 在ISO C++类周围编写一个包装器C++ .Net类
  2. 从C#中使用C++ .Net类

我有以下问题:

  • 首先,这是实现将C++类暴露给C#的目标的"最佳"方式吗?
  • 到目前为止,我还没有看到任何实际显示如何执行此操作的示例 - 任何人都可以建议一些链接,或者代码片段来显示如何为虚拟类完成此操作?
  • 如何从C++代码向C#代码发送异步消息通知?理想情况下,我想使C#类引发事件,并将接收到的数据作为参数

c# c++ mono pinvoke c++-cli

14
推荐指数
1
解决办法
3234
查看次数

没有找到入口点的例外

我正在尝试在C#项目中使用C++非托管dll,并且在尝试调用一个无法找到入口点的函数时遇到错误.

public class Program
{

    static void Main(string[] args)
    {
        IntPtr testIntPtr = aaeonAPIOpen(0);            
        Console.WriteLine(testIntPtr.ToString());
    }

    [DllImport("aonAPI.dll")]
    public static extern unsafe IntPtr aaeonAPIOpen(uint reserved);
}
Run Code Online (Sandbox Code Playgroud)

这是函数的dumpbin:

5    4 00001020 ?aaeonAPIOpen@@YAPAXK@Z
Run Code Online (Sandbox Code Playgroud)

我改变了DLL进口[DllImport("aonAPI.dll", EntryPoint="?aaeonAPIOpen")][DllImport("aonAPI.dll", EntryPoint="_aaeonAPIOpen")]和没有运气.

c# pinvoke interop

14
推荐指数
2
解决办法
2万
查看次数

当你有句柄时,int vs IntPtr?

首先是一个背景问题:

一般来说,int和之间有什么区别IntPtr?我的猜测是它是一个实际的对象,而不是像int或是一个值byte.假设是真的:

所以他们不一样.然而,我看到手柄代表两者.

  1. IntPtr的: Control.Handle
  2. int(或uint):PInvoke可以设置为返回一个int并且它可以正常工作:

    [DllImport("coredll.dll", SetLastError = true)]
    public static extern int GetForegroundWindow();
    private string GetActiveWindow()
    {
        const int nChars = 256;
        int handle = 0;
        StringBuilder Buff = new StringBuilder(nChars);
    
        handle = CoreDLL.GetForegroundWindow();
    
        if (CoreDLL.GetWindowText(handle, Buff, nChars) > 0)
        {
            return Buff.ToString();
        }
    
        return "";
    }
    
    Run Code Online (Sandbox Code Playgroud)

那么,intvs IntPtr?手柄有问题吗?你能用吗?

c# pinvoke

14
推荐指数
1
解决办法
7783
查看次数

如何编写允许数据从本机流向托管的自定义封送程序?

在尝试编写与此问题相关的自定义封送程序(P/Invoke从C到C#而不知道数组的大小)时,我遇到了一些我无法理解的问题.这是我写的第一个定制封送器,所以毫无疑问,由于我的无知,我错过了一些明显的东西.

这是我的C#代码:

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace CustomMarshaler
{
    public class MyCustomMarshaler : ICustomMarshaler
    {
        static MyCustomMarshaler static_instance;

        public IntPtr MarshalManagedToNative(object managedObj)
        {
            if (managedObj == null)
                return IntPtr.Zero;
            if (!(managedObj is int[]))
                throw new MarshalDirectiveException("VariableLengthArrayMarshaler must be used on an int array.");

            int[] arr = (int[])managedObj;
            int size = sizeof(int) + arr.Length * sizeof(int);
            IntPtr pNativeData = Marshal.AllocHGlobal(size);
            Marshal.WriteInt32(pNativeData, arr.Length);
            Marshal.Copy(arr, 0, pNativeData + sizeof(int), arr.Length);
            return pNativeData;
        }

        public object MarshalNativeToManaged(IntPtr pNativeData)
        {
            int …
Run Code Online (Sandbox Code Playgroud)

c# pinvoke

14
推荐指数
1
解决办法
5809
查看次数

Excel作为WPF中的嵌入框架已禁用ExcelWorksheet

我找到了一个使用Windows 的SetParent()函数在WPF中设置Excel实例的解决方案.

问题是,鼠标和键盘不会对工作表做出反应,而是对工作簿做出反应.

完整示例项目在此处下载

我也试过WindowsFormsHost,但它具有相同的效果.

XAML

<Window x:Class="ExcelEditor.SimpleWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:ExcelEditor"
    mc:Ignorable="d" Loaded="Window_Loaded" Closing="Window_Closing"
    Title="SimpleWindow" Height="450" Width="800">
<Grid x:Name="LayoutRoot">

</Grid>
Run Code Online (Sandbox Code Playgroud)

C#代码

    using System;
    using System.Windows;


namespace ExcelEditor
{
    /// <summary>
    /// Interaktionslogik für SimpleWindow.xaml
    /// </summary>
    public partial class SimpleWindow : Window
    {
        private Microsoft.Office.Interop.Excel.Application ExcelApplication;

        public SimpleWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(this); // <- testing only (no success)
            ExcelApplication = new Microsoft.Office.Interop.Excel.Application();
            ExcelApplication.DisplayAlerts = false;
            System.Windows.Interop.HwndSource …
Run Code Online (Sandbox Code Playgroud)

.net c# windows excel pinvoke

14
推荐指数
1
解决办法
394
查看次数

通过P/Invoke调用GetGUIThreadInfo

我想将键盘输入发送到另一个进程中的窗口,而不将该窗口带到前台.我可以PostMessage用来伪造WM_KEYDOWNWM_KEYUP; 我需要知道的是哪个窗口句柄应该接收键盘输入 - 即类似GetFocus,但是对于另一个非活动应用程序.

GetGUIThreadInfo API看起来很有希望-它返回hwndFocus另一个应用程序.但我没有运气在我的64位操作系统上使用C#工作.我已经复制(然后进一步调整)来自pinvoke.net的声明,但我所得到的只是一般错误代码(下面有更多详细信息).

我在调用GetGUIThreadInfo之前设置了cbSize,所以我避免了最明显的潜在问题.

我正在运行64位Vista,所以我不知道问题是我没有正确使用API​​,还是64位工作方式不同 - 我还没找到具体的代码示例说它在Win64中成功运行.

这是示例代码.我按照建议使用GetWindowThreadProcessId ,所以我不认为问题与将线程ID与线程句柄混合有关:

[StructLayout(LayoutKind.Sequential)]
internal struct Rect
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

[StructLayout(LayoutKind.Sequential)]
internal class GuiThreadInfo
{
    public int cbSize;
    public uint flags;
    public IntPtr hwndActive;
    public IntPtr hwndFocus;
    public IntPtr hwndCapture;
    public IntPtr hwndMenuOwner;
    public IntPtr hwndMoveSize;
    public IntPtr hwndCaret;
    public Rect rcCaret;
}

[DllImport("user32.dll")]
internal …

c# pinvoke

13
推荐指数
1
解决办法
2808
查看次数

使用c#删除外部应用程序的标题栏

我的应用程序启动了另一个外部应用

我想在启动后删除此外部应用程序的标题栏.

这是可行的,如果是这样的话怎么办?

根据评论,我使用下面的工作代码

//Finds a window by class name
[DllImport("USER32.DLL")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

//Sets a window to be a child window of another window
[DllImport("USER32.DLL")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

//Sets window attributes
[DllImport("USER32.DLL")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

//Gets window attributes
[DllImport("USER32.DLL")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);


//assorted …
Run Code Online (Sandbox Code Playgroud)

c# pinvoke process winforms

13
推荐指数
3
解决办法
2万
查看次数

如何在32位平台上pinvoke到GetWindowLongPtr和SetWindowLongPtr?

我想P/Invoke到GetWindowLongPtrSetWindowLongPtr,我看到有关它们的相互矛盾的信息.

有些消息称,在32位平台上,GetWindowLongPtr只是一个调用GetWindowLong的预处理器宏,而GetWindowLongPtr不作为user32.dll中的入口点存在.例如:

  • SetWindowLongPtrpinvoke.net条目有一个静态方法,它检查IntPtr.Size,然后调用SetWindowLong或SetWindowLongPtr,注释说"遗留操作系统不支持SetWindowLongPtr".没有解释"遗留操作系统"的含义.
  • StackOverflow答案是 "On 32bit系统GetWindowLongPtr只是一个指向GetWindowLong的C宏".

因此,这些来源似乎表明*Ptr入口点根本不存在于32位Windows 7附带的user32.dll版本中.

但我在MSDN文档中没有看到这一点.根据MSDN,SetWindowLongPtr取代了SetWindowLong,简单明了.根据SetWindowLongPtr页面的要求部分,看起来SetWindowLongPtr自Windows 2000(客户端和服务器版本)以来一直在user32.dll中.同样,没有提到32位操作系统中缺少的入口点.

怀疑事实介于两者之间:当你告诉C++编译器定位较旧的操作系统(即编译将在Win9x和NT4上运行的东西)时,头文件将SetWindowLongPtr声明为调用SetWindowLong的宏,但是入口点可能确实存在于Windows 2000及更高版本中,如果您告诉编译器定位这些平台,您将直接获取它(而不是宏).但这只是猜测; 我真的没有资源或技术可以深入挖掘并验证它.

目标平台也可能扮演一个角色 - 如果您为x86平台编译应用程序,那么就不应该在64位操作系统上调用SetWindowLongPtr.再一次,我知道这个问题,但我不知道如何找到答案.MSDN似乎暗示SetWindowLongPtr始终是正确的.

任何人都可以告诉我,简单的P/Invoke到SetWindowLongPtr是否安全并完成它?(假设Windows 2000及更高版本.)P /调用SetWindowLongPtr会给我正确的入口点:

  • 如果我在32位操作系统上运行针对x86平台的应用程序?
  • 如果我在64位操作系统上运行针对x86平台的应用程序?
  • 如果我在64位操作系统上运行针对x64平台的应用程序?

.net c# pinvoke getwindowlong setwindowlong

13
推荐指数
1
解决办法
7915
查看次数

P /调用C#和.NET时的功能检测

我正试图在P/Invoking之前找到一种检测特征是否存在的好方法.例如,调用本机StrCmpLogicalW函数:

[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
   [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
   public static extern int StrCmpLogicalW(string psz1, string psz2);
}
Run Code Online (Sandbox Code Playgroud)

将在某些没有此功能的系统上崩溃.

我不想执行版本检查,因为这是不好的做法,有时可能只是错误(例如,当功能被反向移植时,或者可以卸载功能时).

正确的方法是检查导出的存在shlwapi.dll:

private static _StrCmpLogicalW: function(String psz1, String psz2): Integer;
private Boolean _StrCmpLogicalWInitialized;

public int StrCmpLogicalW(String psz1, psz2)
{
    if (!_StrCmpLogialInitialized)
    {
        _StrCmpLogicalW = GetProcedure("shlwapi.dll", "StrCmpLogicalW");
        _StrCmpLogicalWInitialized = true;
    }

    if (_StrCmpLogicalW)
       return _StrCmpLogicalW(psz1, psz2)
    else
       return String.Compare(psz1, psz2, StringComparison.CurrentCultureIgnoreCase);
}
Run Code Online (Sandbox Code Playgroud)

当然,问题是C#不支持函数指针,即:

_StrCmpLogicalW = GetProcedure("shlwapi.dll", "StrCmpLogicalW");
Run Code Online (Sandbox Code Playgroud)

无法做到.

所以我试图找到替代语法来在.NET中执行相同的逻辑.到目前为止我有以下伪代码,但我受到了阻碍:

[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods …
Run Code Online (Sandbox Code Playgroud)

c# pinvoke feature-detection

13
推荐指数
1
解决办法
1137
查看次数