Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

VB.NET и Win32 API не дружат?

17K
07 декабря 2006 года
Conteacky
23 / / 07.12.2006
В VB6 мне почти все понятно, а при попытке перехода на NET сразу неудача. При первом-же опыте с использованием ф-ций API - Debug. Где ошибка?
Код:
Imports System
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

Public Class Form1

    <DllImport("User32.dll", EntryPoint:="FindWindow")> _
    Public Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    End Function

    <DllImport("User32.dll", EntryPoint:="GetWindowTextLength")> _
    Public Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As Integer
    End Function

    <DllImport("User32.dll", EntryPoint:="GetWindowText")> _
    Public Shared Function GetWindowText(ByVal hwnd As IntPtr, _
                                  ByRef lpString As String, _
                                  ByVal cch As Integer) As Integer
    End Function

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim hwnd As IntPtr = FindWindow(vbNullString, "Form1")
        Dim length As Integer = GetWindowTextLength(hwnd)
        Dim sText As String = Space(length)
        Dim Res As Integer = GetWindowText(hwnd, sText, length)
        TextBox1.Text = sText
    End Sub
End Class
273
09 декабря 2006 года
3A3-968M
1.2K / / 22.12.2005
И тут же два входящих вопроса:
1) Что за ошибка. Compile-time или run-time??? И текст её желательно
2) С какой целью WinAPI здесь используешь?? Можно и без него обойтись (в твоём коде точно).
17K
09 декабря 2006 года
Conteacky
23 / / 07.12.2006
PinvokeStackImbalance пишет, да запусти этот код на VS2005 - я пробовал на разных машинах - результат один.
А зчем - нужно запустить EnumChildWindows и получить список окон внутри программы с именами и назв.класса и т.п. В NET, насколько я знаю альтернативы нет
273
10 декабря 2006 года
3A3-968M
1.2K / / 22.12.2005
Цитата: Conteacky

А зчем - нужно запустить EnumChildWindows и получить список окон внутри программы с именами и назв.класса и т.п. В NET, насколько я знаю альтернативы нет


А вот и зря, если нужно перечислить все открытые формы в твоём приложении, то Application.OpenForms. Если все дочерние окна в MDI приложении, то Form.MdiChildren.

17K
10 декабря 2006 года
Conteacky
23 / / 07.12.2006
Цитата:
А вот и зря

Спасибо, я посмотрю. Но ответ не понял - NET & API лучше не смешивать?

273
10 декабря 2006 года
3A3-968M
1.2K / / 22.12.2005
Цитата: Conteacky
Спасибо, я посмотрю. Но ответ не понял - NET & API лучше не смешивать?


Конечно лучше не смешивать, это замедляет работу приложения, может быть причиной Memory Leak, потеря кроссплатформенности.

17K
10 декабря 2006 года
Conteacky
23 / / 07.12.2006
Спасибо, я понял. Но вопросов - тьма, уж больно NET непохож на привычный VB+API. Может подскажешь, где кроме MSDN на англ. можно почерпнуть информацию на русском? Оно конечно и на англ. отчасти понятно, но отчасти.
17K
10 декабря 2006 года
Conteacky
23 / / 07.12.2006
Кстати, вот сразу возник вопрос по Application.OpenForms. Count возвращает 1, т.е. число форм внутри программы, а мне надо получить список ВСЕХ открытых форм. К чему апицепить OpenForms, если не к "Me"? И еще: перечисление окон будет осуществляться в DLL, запускаемой извне, значит "Application" мне тоже не подходит. Уточню задачку: DLL-ке известен на 100% Handle окна программы и больше ничего о ней. Нужно получить список окон со всеми доступными параметрами открытых внутри ее, не обязательно MDI. Ф-ция API EnumChildWindows здесь работает очень четко (правда получаемых параметров маловато). Так как это сделать средствами NET?
273
10 декабря 2006 года
3A3-968M
1.2K / / 22.12.2005
Вот некоторая переведённая часть MSDN на русском: http://msdn.microsoft.com/library/rus/
То что ты хочешь делается так (без WinAPI, чистый managed):
Код:
[SIZE=2][COLOR=#0000ff][FONT=Courier New]Imports[/FONT][/COLOR][/SIZE][SIZE=2][FONT=Courier New] System.Diagnostics[/FONT][/SIZE]
[SIZE=2][COLOR=#0000ff][FONT=Courier New]Imports[/FONT][/COLOR][/SIZE][SIZE=2][FONT=Courier New] System[/FONT][/SIZE]
[SIZE=2][COLOR=#0000ff][FONT=Courier New]Imports[/FONT][/COLOR][/SIZE][SIZE=2][FONT=Courier New] System.Collections[/FONT][/SIZE]
 
[SIZE=2][COLOR=#0000ff][FONT=Courier New]Module[/FONT][/COLOR][/SIZE][SIZE=2][FONT=Courier New] Module1[/FONT][/SIZE]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] Sub[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New] Main()[/FONT][/SIZE]
[FONT=Courier New][SIZE=2][COLOR=#0000ff]   For [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Each[/COLOR][/SIZE][SIZE=2] proc [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Process [/SIZE][SIZE=2][COLOR=#0000ff]In[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New] Process.GetProcesses(Environment.MachineName)[/FONT][/SIZE]
[SIZE=2][FONT=Courier New]     Console.WriteLine([/FONT][/SIZE][FONT=Courier New][SIZE=2][COLOR=#800000]"Main Window Title: {0}"[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New], proc.MainWindowTitle)[/FONT][/SIZE]
[SIZE=2][FONT=Courier New]     Console.WriteLine([/FONT][/SIZE][FONT=Courier New][SIZE=2][COLOR=#800000]"Main Window Handle: {0}"[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New], proc.MainWindowHandle)[/FONT][/SIZE]
[FONT=Courier New][SIZE=2][COLOR=#0000ff]   Next[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New] proc[/FONT][/SIZE]
[SIZE=2][FONT=Courier New]   Console.ReadKey()[/FONT][/SIZE]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] End [/COLOR][/SIZE][/FONT][SIZE=2][COLOR=#0000ff][FONT=Courier New]Sub[/FONT][/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff][FONT=Courier New]End [/FONT][/COLOR][/SIZE][FONT=Courier New][SIZE=2][COLOR=#0000ff]Module[/COLOR][/SIZE][/FONT]

С помощью класса System.Diagnostics.Process узнаешь и о хэндле главного окна, и о HInstance модуля и т.д..
17K
10 декабря 2006 года
Conteacky
23 / / 07.12.2006
Вот спасибо, Только теперь есть Handle, но что-то не соображу, как теперь зацепить саму форму, as Form. Смотрю MSDN
17K
10 декабря 2006 года
Conteacky
23 / / 07.12.2006
Оба-на...Я рано обрадовался. В прецессе не видны дочерние окна, а они-то мне как раз и нужны...
17K
11 декабря 2006 года
Conteacky
23 / / 07.12.2006
Спрошу больше: а можно ли связать System.Diagnostics.Process и Application.OpenForms, чтобы сначала получить список процессов, а потом внутри каждого получить список всех открытых форм. По отдельности - то работают
273
11 декабря 2006 года
3A3-968M
1.2K / / 22.12.2005
Цитата: Conteacky
Спрошу больше: а можно ли связать System.Diagnostics.Process и Application.OpenForms, чтобы сначала получить список процессов, а потом внутри каждого получить список всех открытых форм. По отдельности - то работают


Как вариант можно получать хэндл главного окна процесса, создать экземпляр Form и передать в конструктор этот хэндл. И потом при помощи класса ApplicationContext получить другие окна.

17K
11 декабря 2006 года
Conteacky
23 / / 07.12.2006
Эх, пример бы новичку NET-а
22K
11 декабря 2006 года
cy6erGn0m
5 / / 11.12.2006
Потеря кроссплатформенности? так она и так не используется пока что...все равно без толку...вот когда заработают под *nix как следует, тогда можно будет об этом говорить... хотя что правда то правда...
утчеки памяти при грамотном обращении случиться не должно.
Насчёт потери производительности, это тоже не факт... .net сама по себе делает много всяких действий и в итоге обращается к API. Накладные расходы на вызов API функции могут окупиться....

Против смешивания .NET и API явное наршение общего стиля при том, что явно редко возникает необходимость в его использовании из под .NET
5
11 декабря 2006 года
hardcase
4.5K / / 09.08.2005
Цитата: cy6erGn0m
Потеря кроссплатформенности? так она и так не используется пока что...


платформа - это не только операционная система. это скорее операционная система + аппаратное обеспечение.

Цитата: cy6erGn0m
утчеки памяти при грамотном обращении случиться не должно.

Не должно. А утечки бывают и не только при обращении к Win32API.
Не каждый вот так сразу сможет написать заголовок к апишке.

Цитата: cy6erGn0m

Насчёт потери производительности, это тоже не факт... .net сама по себе делает много всяких действий и в итоге обращается к API. Накладные расходы на вызов API функции могут окупиться....


Это как-то сомнительно. Скорее всего это приведёт - это к потере читабельности кода.

К томуже в Висте Win32 API уже как таковых нет. Есть WinFX, частью которой является MSFw.

22K
11 декабря 2006 года
cy6erGn0m
5 / / 11.12.2006
в общем итоге спору и нет о том, что вызывать API из под .net это плохая идея...в этом просто нет смысла...для больших программ это плохо, потому что снижет читабельность и усложнит дальнейшую поддержку проекта, а для маленьких, потому что маленькую при ОЧЕНЬ уж большой надобности можно написать и на си.
17K
12 декабря 2006 года
Conteacky
23 / / 07.12.2006
Цитата:
вызывать API из под .net это плохая идея

Правильно, но тем не менее ьез API порой не обойтись, и делать это нужно аккуратно. Посмотрите http://www.codeproject.com/ - ярые поклонники NET не стесняются применять функции API

17K
12 декабря 2006 года
Conteacky
23 / / 07.12.2006
Вопрос к ЗАЗ-968М:
Цитата:
получать хэндл главного окна процесса, создать экземпляр Form и передать в конструктор этот хэндл

Есть хендл, есть New Form. Подскажи, что дальше.

17K
12 декабря 2006 года
Conteacky
23 / / 07.12.2006
Впрочем разобрался:
 
Код:
Dim FM As Form
        FM = Form.FromHandle(hwnd)
И могу работать дальше
17K
12 декабря 2006 года
Conteacky
23 / / 07.12.2006
Не все так просто. С помощью FromHandle форму я получаю, а вот как выйти на Application, зная Handle главного окна программы? Имея форму, я могу получить список контролов на ней, а список дочерних окон главного окна не получается. OpenForms просит Application.
Могучий ЗАЗ, вытягивай.
5
12 декабря 2006 года
hardcase
4.5K / / 09.08.2005
попробовал вот так (сорри, что на C#):
 
Код:
foreach (Process p in Process.GetProcesses( )) {
    Control mainForm = Control.FromHandle(p.MainWindowHandle);
    if (mainForm == null)
        continue;
    textBox1.Text += p.ProcessName + " " + mainForm.Text + "\r\n";
    foreach (Control c in mainForm.Controls) {
        textBox1.Text += "     " + c.Text + "\r\n";
    }
}

Control.FromHandle возвращет объект только если хэндл принадлежит нашему приложению.

Может нет каких-то прав вроде UIPermission?
17K
13 декабря 2006 года
Conteacky
23 / / 07.12.2006
Спасибо, с методами я вроде бы разобрался. Но остались непонятки: hendle чужого окна мне известен 100%. API по нему работает четко - получаю и имя класса и заголовок окна, а вот NET спотыкается - пытаюсь получить форму по hendle через FromHandle - тип полученного значения выдает как "Nothing", т.е. не срабатывает. Соответственно вопрос:"Почему такое может быть?". И, если известно имя класса, может его можно использовать при получении формы, как объект "Form".
Собственно моя заковырка вот в чем - мне нужно получить имя (не заголовок) окна или найти окно по имени (не по заголовку). Ф-ции API с именем не работают, NET не работает с handle (в моем случае). Как быть?
MFC позволяет это решить, но с С++ я не работаю. Кстати, а нельзя ли классы MFC к NETу прицепить?
273
13 декабря 2006 года
3A3-968M
1.2K / / 22.12.2005
Ладно ладно, убедил что без WinAPI не обойтись. В этом случае тебе на www.pinvoke.net. Там есть импорты любых функций из WinAPI на VB.NET и C#.
17K
13 декабря 2006 года
Conteacky
23 / / 07.12.2006
Цитата:
Там есть импорты любых функций из WinAPI

Спасибо. С API я вроде как разобрался. И с NET немного тоже. Остается их как-то связать. Пока моя задача осталась невыполнимой, а именно получить хендл форма (контрола) по его Name (не по заголовку).
Немного приоткрою завесу таинственности: пишу DLL для с..кой пронраммы 1С. Для функционирования большинства ф-ции (они из API) требуется хендл. Свойства формы/контрола Handle/hwnd в 1С нет, форма 1С не может иметь меню, больше половины типов контролов не имеют свойства "Заголовок". Свойство "Имя" есть у всех контролов, но нет у формы. Вот и головоломкаЮ получить хендл. Скажу сразу, хендл формы 1С я все-таки получил (хитрая получилась технология). Для контролов, имеющих свойство "Заголовок" - тоже могу получить. А вот для контролов, имеющих только имя - бьюсь.

273
13 декабря 2006 года
3A3-968M
1.2K / / 22.12.2005
Обратись в раздел WinAPI. Тебе там подскажут как это сделать через WinAPI на C++. Потом результаты пости сюда, прикрутим всё это к .NET
17K
13 декабря 2006 года
Conteacky
23 / / 07.12.2006
Хорошо.
Я сейчас смотрю, как у нормальных людей сделано все это для 1С на C++/MFC. Но мне кажется классы MFC вряд ли прикрутишь к VB/C#. В С++ точно используется CWmd. На С++ у меня пока импотенция. А только средствами API получить имя окна по хендлу (а это мне и нужно после Enum) не получится. В общем есть список контролв, вернее их hwnd & Caption & ClassName, нет Name.
273
14 декабря 2006 года
3A3-968M
1.2K / / 22.12.2005
Цитата: Conteacky
Хорошо.
Я сейчас смотрю, как у нормальных людей сделано все это для 1С на C++/MFC. Но мне кажется классы MFC вряд ли прикрутишь к VB/C#. В С++ точно используется CWmd. На С++ у меня пока импотенция. А только средствами API получить имя окна по хендлу (а это мне и нужно после Enum) не получится. В общем есть список контролв, вернее их hwnd & Caption & ClassName, нет Name.


Приведи нужные функции WinAPI (ведь MFC использует WinAPI), я тебе их переведу на VB.NET.

17K
14 декабря 2006 года
Conteacky
23 / / 07.12.2006
Чуть позже.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог