当前位置:编程学习 > C#/ASP.NET >>

【求助】WinAPI也无法将最小化的窗口还原??(前一帖错漏多,不好意思,重发)

不好意思,心急,发漏了一个条件,现在补充一下:

我想在我的程序中打开“计算器”,若计算器未打开就启动一个,若已经打开,就激活它并前端显示。
这个问题本来GOOGLE一下,大概答案不少,一般都是使用winAPI的“ShowWindow”、“SendMessage”等等,但是我还是遇到困难,问题是这样的:若计算器程序首先打开,然后鼠标点击让其最小化后,再运行下面程序,这样就无论如何达不到效果!!!
测试程序中一个按钮的执行代码:

'==============API声明开始==================


  Public Const SW_HIDE = 0
  Public Const SW_SHOWNORMAL = 1
  Public Const SW_SHOWMINIMIZED = 2
  Public Const SW_SHOWMAXIMIZED = 3
  Public Const SW_MAXIMIZE = 3
  Public Const SW_SHOWNOACTIVATE = 4
  Public Const SW_SHOW = 5
  Public Const SW_MINIMIZE = 6
  Public Const SW_SHOWMINNOACTIVE = 7
  Public Const SW_SHOWNA = 8
  Public Const SW_RESTORE = 9
  Private Const SW_SHOWDEFAULT = 10
  Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long

  Private Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long

  Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

  Public Const WM_SYSCOMMAND = &H112
  Public Const SC_CLOSE = &HF060& '关闭窗体
  Public Const SC_MINIMIZE = &HF020& '最小化窗体
  Public Const SC_MAXIMIZE = &HF030& '最大化窗体
  Public Const SC_RESTORE = &HF120& '恢复窗体大小
  Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

'==============API声明结束==================

  Private Sub btTEST_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

  Dim pro As Process() = Diagnostics.Process.GetProcessesByName("calc")

  If pro.Length >= 1 Then
  '方法0:SendMessage(结果明显看见任务栏中的计算器被选中了,可就是不显示到前端)
  'SendMessage(FindWindow(vbNullString, "计算器"), WM_SYSCOMMAND, SC_MAXIMIZE, 0)
  'SetForegroundWindow(FindWindow(vbNullString, pro(0).MainWindowTitle))

  '方法1:SendMessage(结果明显看见任务栏中的计算器被选中了,可就是不显示到前端)
  'SendMessage(FindWindow(vbNullString, pro(0).MainWindowTitle), WM_SYSCOMMAND, SC_MAXIMIZE, 0)
  'SetForegroundWindow(FindWindow(vbNullString, pro(0).MainWindowTitle))

  '方法2:ShowWindow(结果明显看见任务栏中的计算器被选中了,可就是不显示到前端)
  ShowWindow(FindWindow(vbNullString, pro(0).MainWindowTitle), SW_RESTORE)
  SetForegroundWindow(FindWindow(vbNullString, pro(0).MainWindowTitle))

  '方法3:ShowWindow(不使用FindWindow,但是结果是计算器的窗口消失了,可是进程还在,好像隐藏的效果)
  'ShowWindow(pro(0).MainWindowHandle.ToInt32, 9)
  'SetForegroundWindow(FindWindow(vbNullString, pro(0).MainWindowTitle))

  Me.WindowState = FormWindowState.Minimized  '最小化自己
  Else
  Shell("C:\WINDOWS\system32\calc.exe", AppWinStyle.NormalFocus)
  End If

  End Sub --------------------编程问答-------------------- 我自己终于找到答案了:

1、为什么VB.NET中process.MainWindowHandle.ToInt32和Win32API中FindWindow返回值不同?
2、为什么SendMessage、ShowWindow等API函数总是调用失败?
很多问题,曾经困扰我一天,原来TMD是数据类型问题,以下是VB6.0中的API定义:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

因为VB.net和VB6的数据类型LONG的定义已经不一样了,在VB.NET里long是64位,而窗口句柄仍然是32位, 所以得不到正确的返回值,只要将long改成integer就好了: 
Declare Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer 

唉,希望给各位兄弟提个醒,高手们可以无视,请宽恕我这个菜鸟!  --------------------编程问答-------------------- 没这么复杂。简单点
Module Module1
    Public Declare Function SetForegroundWindow Lib "user32" Alias "SetForegroundWindow" (ByVal hwnd As Integer) As Integer
    Sub Main()
        Dim cur As Process = Process.GetCurrentProcess()
        For Each p As Process In Process.GetProcesses
            If p.Id = cur.Id Then Continue For
            If p.ProcessName = cur.ProcessName Then
                SetForegroundWindow(p.MainWindowHandle)
                Return
            End If
        Next
        Application.Run(New Form9)
    End Sub
End Module
--------------------编程问答-------------------- 仔细看,才知道你还要在最小化的时候处理,这样,稍微修改一点。

Module Module1
    Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer
    Public Declare Function SetForegroundWindow Lib "user32" Alias "SetForegroundWindow" (ByVal hwnd As Integer) As Integer
    Public Const WM_SYSCOMMAND = &H112
    Public Const SC_RESTORE = &HF120&
    Sub Main()
        Dim cur As Process = Process.GetCurrentProcess()
        For Each p As Process In Process.GetProcesses
            If p.Id = cur.Id Then Continue For
            If p.ProcessName = cur.ProcessName Then
                SetForegroundWindow(p.MainWindowHandle)
                SendMessage(p.MainWindowHandle, WM_SYSCOMMAND, SC_RESTORE, IntPtr.Zero)
                Return
            End If
        Next
        Application.Run(New Form9)
    End Sub
End Module
--------------------编程问答-------------------- VB6跟VB.NET在对API函数进行声明时是要进行类型转换的。看来只能接分了
补充:.NET技术 ,  VB.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,