Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / А как сделать SendMessage, если lParam - структура? / 10 сообщений из 10, страница 1 из 1
13.09.2013, 18:36
    #38396426
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
Пример VB6:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
 (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

  Dim rbBand As REBARBANDINFO
  With rbBand
    .cbSize = LenB(rbBand)
    .fMask = RBBIM_COLORS Or RBBIM_CHILD Or RBBIM_CHILDSIZE Or RBBIM_STYLE Or _
     RBBIM_ID
    .fStyle = RBBS_NOVERT Or RBBS_GRIPPERALWAYS
    OleTranslateColor vbButtonText, 0, .clrFore
    OleTranslateColor vbButtonFace, 0, .clrBack
    .hwndChild = g_hwndToolBar
    .wID = ID_TOOLBAR
    .cxMinChild = 170 '100
    .cyMinChild = 33
  End With
 
  ' Insert band into rebar
  SendMessage hwndParent, RB_INSERTBAND, -1, rbBand



Пытаюсь (NET), естественно с Marshal пробую проделав уже какой-то поиск в инете:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
Imports System.Runtime.InteropServices

  Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
   (ByVal hwnd As IntPtr, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As IntPtr) As Integer

    Dim rbBand As REBARBANDINFO
    With rbBand
      .cbSize = Marshal.SizeOf(rbBand)
      .fMask = ReBarBandInfoMasks.RBBIM_COLORS Or ReBarBandInfoMasks.RBBIM_CHILD Or _
       ReBarBandInfoMasks.RBBIM_CHILDSIZE Or ReBarBandInfoMasks.RBBIM_STYLE Or _
       ReBarBandInfoMasks.RBBIM_ID
      .fStyle = ReBarBandStyles.RBBS_NOVERT Or ReBarBandStyles.RBBS_GRIPPERALWAYS
      .clrFore = System.Drawing.ColorTranslator.ToWin32(Color.FromKnownColor(KnownColor.ControlText))
      .clrBack = System.Drawing.ColorTranslator.ToWin32(Color.FromKnownColor(KnownColor.ButtonFace))
      .hwndChild = Form1.ToolBar1.Handle
      .wID = ID_TOOLBAR
      .cxMinChild = 170 '100
      .cyMinChild = 33
     End With

    ' Insert band into rebar

    Dim structPtr As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(rbBand))
    Marshal.StructureToPtr(rbBand, structPtr, False)
    SendMessage(g_hwndRebar, RB_INSERTBAND, -1, structPtr)
    Marshal.FreeCoTaskMem(structPtr)


Выдает указывая на structPtr в SendMessage:
Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена.

Чнго делать в таких случаях? Без API никак -нужен Rebar/Coolbar с поддеркой тем (Communication, Media итд.), а не порноStrip.
Максимум на что рассчитываю, вставить в API ребар Net-Toolbar (он Common Controls) или даже Strip(но надо смотреть) -по идее это должно прокатить.

Но интересует общий принцип передачи структуры в последнем параметре SendMessage -без этого жизнь не наладится.
...
Рейтинг: 0 / 0
13.09.2013, 19:38
    #38396466
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
Дмитрий77
Код: vbnet
1.
2.
3.
4.
5.
Imports System.Runtime.InteropServices

  Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
   (ByVal hwnd As IntPtr, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As IntPtr) As Integer
...


Выдает указывая на structPtr в SendMessage:
Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена.
Короче "сам дурак".
Забыл сделать Long->Integer.

Все заработало.
Либо так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
  Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
   (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer

    ' Insert band into rebar
    Dim structPtr As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(rbBand))
    Marshal.StructureToPtr(rbBand, structPtr, False)
    SendMessage(g_hwndRebar, RB_INSERTBAND, -1, structPtr)
    Marshal.FreeCoTaskMem(structPtr)


Либо так:
Код: vbnet
1.
2.
3.
4.
5.
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
   (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As REBARBANDINFO) As Integer

    ' Insert band into rebar
    SendMessage(g_hwndRebar, RB_INSERTBAND, -1, rbBand)



Сюда вопрос:
Я вставляю [.NET]Toolbar1 в банд:
Код: vbnet
1.
2.
      .hwndChild = Form1.ToolBar1.Handle
      .wID = ID_TOOLBAR


-все вставляется.

Я хочу попробовать то же самое с [.NET]ToolStrip
Все-таки у стрипа больше штатных возможностей и стили он ПСЕВДО -поддерживает (хотя они и "рисованные" а не Common Controls, но "похоже").

Я попытался сделать:
Код: vbnet
1.
.hwndChild = Form1.ToolStrip1.Handle


ToolStrip1 с формы исчез, а в банде(в ребар) не появился.
Решаемо?
...
Рейтинг: 0 / 0
14.09.2013, 01:32
    #38396585
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
Дмитрий77Но интересует общий принцип передачи структуры в последнем параметре SendMessage -без этого жизнь не наладится.
Код: c#
1.
2.
3.
4.
GCHandle lp =GCHandle.Alloc(o);
IntPtr p = lp.AddrOfPinnedObject();
            ...
lp.Free();
...
Рейтинг: 0 / 0
14.09.2013, 01:50
    #38396588
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
в первой строке параметр добавить - GCHandle.Alloc(o, GCHandleType.Pinned);
...
Рейтинг: 0 / 0
14.09.2013, 11:09
    #38396635
fortibransa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
Вот нахрена это все тебе, 100% что в NET все что надо тебе есть и без SendMessage
...
Рейтинг: 0 / 0
15.09.2013, 00:48
    #38396902
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
Изопропил
Код: c#
1.
2.
3.
4.
GCHandle lp =GCHandle.Alloc(o);
IntPtr p = lp.AddrOfPinnedObject();
            ...
lp.Free();


...в первой строке параметр добавить
Вот так работает (то же на VB.NET):
Код: vbnet
1.
2.
3.
4.
    Dim lp As GCHandle = GCHandle.Alloc(rbBand, GCHandleType.Pinned)
    Dim p As IntPtr = lp.AddrOfPinnedObject()
    SendMessage(g_hwndRebar, RB_INSERTBAND, -1, p)
    lp.Free()



Но коль предложили этот вариант, то вопрос.
Чем он лучше Marshal-а?
Дмитрий77Либо так:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
  Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
   (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer

    ' Insert band into rebar
    Dim structPtr As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(rbBand))
    Marshal.StructureToPtr(rbBand, structPtr, False)
    SendMessage(g_hwndRebar, RB_INSERTBAND, -1, structPtr)
    Marshal.FreeCoTaskMem(structPtr)


На первый взгляд оба кода имеют один и тот же смысл. На Marshal в поиске натыкаешься чаще (вроде как).

fortibransaВот нахрена это все тебе, 100% что в NET все что надо тебе есть и без SendMessage
fortibransa, нет проблем.

Мне надо:
Код: vbnet
1.
SetWindowTheme g_hwndRebar, StrPtr("Communications"), 0 'синий системный градиент


Код: vbnet
1.
SetWindowTheme g_hwndToolbar, StrPtr("Communications"), 0 'белые буквы на кнопках - системно


(смотри картинку ниже чего делают эти 2 строчки)
И я это не сегодня придумал:
Градиенты в Vista стиле, и в частности подложка под Toolbar.
Дык вот, раз 100% в .Net все есть, объясни мне тупому как к Net.ToolStrip применить данный стиль (средствами .NET).
Заметь, я не разрисовываю контрол Net-фломастерами, я применяю стиль.

Сразу могу сказать следующее:
Если брать .Net. Toolbar (который по умолчанию "задвинут"), то стиль таким образом к нему применяется .
(но это только кнопки с белым шрифтом, а не синяя подложка)
Если брать .Net. Toolstrip то стиль к нему НЕ применяется .
Синяя подложка - это Rebar (Coolbar). В .NET ребар отсутствует,
а ToolStrip данному стандарту не удовлетворяет (хотя как я написал выше его м.б. можно вставить в ребар (API-шный, других вариантов не вижу), но при этом задавать белый шрифт кнопок вручную - и м.б. "прокатит")
...
Рейтинг: 0 / 0
15.09.2013, 01:36
    #38396909
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
Дмитрий77Но коль предложили этот вариант, то вопрос.
Чем он лучше Marshal-а?

Позволяет фиксировать структуру в памяти после вызова P/Invoke( API может требовать буфера, живущего между вызовами)

Ну и просто получать адрес структуры для последующей передачи в произвольные API

Обрати внимание ещё на пару методов - ToIntPtr , FromIntPtr и свойство Target
http://msdn.microsoft.com/en-us/library/vstudio/system.runtime.interopservices.gchandle.target(v=vs.100).aspx

P.S. А на кой эти танцы с бубном, не проще ли просто на C++ писать?
...
Рейтинг: 0 / 0
15.09.2013, 05:00
    #38396922
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
ИзопропилДмитрий77Но коль предложили этот вариант, то вопрос.
Чем он лучше Marshal-а?
Позволяет фиксировать структуру в памяти после вызова P/Invoke( API может требовать буфера, живущего между вызовами)
Ну и просто получать адрес структуры для последующей передачи в произвольные API?
Звучит убедительно. На данном этапе мне проще просто принять твой вариант "на веру".

ИзопропилP.S. А на кой эти танцы с бубном, не проще ли просто на C++ писать?
Мне не проще. Кроме хитрых штук которые решаются через API (для чего C++ согласен оптимален), есть еще куча просто кнопок, текстовых полей, что лучше и проще рисовать в конструкторе и использовать готовые контролы с готовыми событиями и т.д. Я не готов например все кнопки делать через CreateWindow.
VB здесь удобнее (вы можете возразить), но веский аргумент, что я к VB6 привык.

В VB6 бросаешь на форму готовый шаблон (пусть с ограниченными возможностями но он родной Win32 Common Control), пользуешься штатными возможностями при необх. допиливаешь через API.

В .Net с одной стороны штатных возможностей больше (на что ставки - это экономия ресурсов).
С другой стороны подвох. Половина контролов "не настоящие", я этого не люблю.
Напр.,
Net.Toolbar -настоящий Common Control
Net. ToolStrip -не настоящий, хотя при соотв. настройках и "косит под систему".

MainMenu -настоящее меню.
MenuStrip -рисовка, и на >=Виста выглядит существенно хуже штатных менюшек.

Надо щупать короче.

Просто VB6 морально устарел - очень многие стандартные вещи приходится делать через API и ручками -те же InitCommonControls, 32-битные иконки, манифесты.
Потом C++ -очень много споров про всякие str типы-ф-ции -какая-то фигня может в ветке форума обсуждаться взахлеб неделю.
Я не люблю кучу умных фраз, хочется все-таки побыстрее практически и визуально ощутимого результата.
...
Рейтинг: 0 / 0
15.09.2013, 22:22
    #38397155
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
Изопропил,

А вообще я тут подумал.
Остановлюсь ка я на технологии:
Код: vbnet
1.
2.
  Private Declare Function SendMessage_REBARBANDINFO Lib "user32" Alias "SendMessageW" _
   (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As REBARBANDINFO) As Integer


Раз уж As Any недоступна, то проще несколько раз объявить API чем мудохаться с Marshal, GCHandle и писать кучу заумного кода.
По крайней мере с
ByRef структура
работать яснее и прозрачней.

И потом, в приведенном примере структура передавалась в ф-цию,
а в ряде случаев структура содержит результат.
Ниже пример в котором "Заумный код" в лоб не сработал (очевидно нужен другой прием чтоб записать в структуру):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
  Private Declare Function SendMessage_TBBUTTON Lib "user32" Alias "SendMessageW" _
   (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As TBBUTTON) As Integer
  Private Declare Function SendMessage_TBBUTTONINFO Lib "user32" Alias "SendMessageW" _
   (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As TBBUTTONINFO) As Integer

    'установка автоширины для всех кнопок (по ширине надписи)
    Dim ButtonCount As Integer = SendMessage(Form1.ToolBar1.Handle, TB_BUTTONCOUNT, 0, IntPtr.Zero)
    If ButtonCount > 0 Then
      Dim tBB As TBBUTTON
      Dim tBI As TBBUTTONINFO
      tBI.cbSize = Marshal.SizeOf(tBI)
      tBI.dwMask = TBIF_STYLE
      For iButton As Integer = 0 To ButtonCount - 1
        SendMessage_TBBUTTON(Form1.ToolBar1.Handle, TB_GETBUTTON, iButton, tBB)
        SendMessage_TBBUTTONINFO(Form1.ToolBar1.Handle, TB_GETBUTTONINFO, tBB.idCommand, tBI)
        If (tBI.fsStyle And ToolbarButtonStyles.BTNS_SEP) = False Then
          tBI.fsStyle = tBI.fsStyle Or ToolbarButtonStyles.BTNS_AUTOSIZE
          SendMessage_TBBUTTONINFO(Form1.ToolBar1.Handle, TB_SETBUTTONINFO, tBB.idCommand, tBI)
        End If
      Next
    End If


Подумаешь, 2 раза объявил SendMessage, зато все просто, ясно, прозрачно и работоспособно.
...
Рейтинг: 0 / 0
17.09.2013, 08:03
    #38398296
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
А как сделать SendMessage, если lParam - структура?
Дмитрий77Половина контролов "не настоящие", я этого не люблю.

в WPF и Qt,например, - все контролы "ненастоящие"
"Настоящие" - это тяжкое наследие Windows 1.0
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / А как сделать SendMessage, если lParam - структура? / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]