Question

Get Visual Basic 6.0 'Form' object from a known HWnd value...

Asked by: WarpNine

Can someone PLEASE give me some direction on how to create a Visual Basic Form object from an HWnd value? I am only concerned with 'ThunderRT6FormDC' type forms. My ultimate goal is to be able to get the names and other properties of all controls on the form. I'm already able to get the 'ClassName' values of everything, but I need to be able to get the names.

Someone please respond! I need a solution for this issue ASAP! If you need more details, just reply and let me know.

Thanks in advance,

Warp

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2007-01-20 at 15:24:43ID22130256
Tags

basic

,

get

,

visual

,

form

Topics

Visual Basic Programming

,

Microsoft Programming

Participating Experts
5
Points
500
Comments
15

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. HWND of a CDialog...
    Hey, Continuing with my problem for having a CDialog automatically closed after a while, I need to pass the handle window parameter of the CDialog I want to send the message WM_CLOSE. I have spend plenty of hours searching for a way to have the HWND of that Dialog unsucessfu...
  2. Hwnd
    Alot of API uses the Hwnd thing, which tell what window to use. Its easy to incluse this into forms, form1.hwnd.... but is there a way i can use it on other window's forms?
  3. HWND of the browser in ActiveX
    Hi, I have an ActiveX that is loaded from the browser (using OBJECT tag) and I need HWND for a function in one of the dlls that I'm loading (in the ActiveX). Any idea ?
  4. hWnd
    I would like my programm to change the url of my browser. I know I have to use: ::ShellExecute(hWnd, NULL, _T("http://www.experts-exchange.com"), NULL, NULL, SW_SHOWNORMAL); but I don't know how to get hWnd for the browser window. What I want is my programm to g...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: Idle_MindPosted on 2007-01-20 at 21:03:39ID: 18358702

Is this hWnd from your app or an external app?

 

by: JR2003Posted on 2007-01-21 at 14:57:33ID: 18361393

Have you tried using the controls collection on the form?

 

by: AzraSoundPosted on 2007-01-21 at 15:03:21ID: 18361418

If its the same app, then simply looping through the Forms collection should suffice, but I'm not aware of any relationship of window handle and form object if that handle is coming from an external app.  However, there are many API functions that work on a window based on its handle.  What exactly do you need to do once you locate this form you want to work with?

 

by: JR2003Posted on 2007-01-21 at 15:27:50ID: 18361506

Have you tried using the Spy software that comes in the tools options with Visual Studio?

 

by: WarpNinePosted on 2007-01-21 at 21:01:55ID: 18362869


I'm familiar with looping through the Forms collection internally, I'm looking for an 'external' reference of a running (VB6) application. I already have most of what I need, but I can't seem to marry each control with it's hwnd handle...

Here's where I am now...

Method #1:
I'm enumerating using 'EnumWinProc()' and 'EnumChildProc()' which gives me class names from 'GetClassName()' and the controls' text from 'GetWindowText()'. I have the hwnd of my controls here, but I do not have the actual '.Name' of the control...

Method #2:
Now, if I pass the form's hwnd into the 'GetWindowThreadProcessId()' and hop through heap-addresses using 'ReadProcessMemory()' I can get the class name, caption text, and the actaul '.Name' values of the controls! Needless to say I was pleased! But I don't have an hwnd for the controls with this method!

The only remaining issue (for 500 points) is associating the two so that I can have the 'name' of the control AND the 'hwnd' as well. I can't find a way to directly associate the information in method #1 with the information in method #2.

I'm almost there!

Warp

 

by: ArkPosted on 2007-01-23 at 15:58:09ID: 18381058

>>Method #2:
Now, if I pass the form's hwnd into the 'GetWindowThreadProcessId()' and hop through heap-addresses using 'ReadProcessMemory()' I can get the class name, caption text, and the actaul '.Name' values of the controls!<<

It's strange! Actually, controls "Name" property is using in high level languages just to simplify programming. When compiled, control name go out - compiler just place each control code to predefined offsets. Try to disassembly vb executable - you won't find control's names there (not sure, probably compiling using P-code still keep names?)

 

by: JR2003Posted on 2007-01-23 at 16:25:59ID: 18381263

I think that the internal name from for the control is not available outside the application.
This would be a very poor security feature of vb if it did allow you to see the name of the controls in the form.

 

by: WarpNinePosted on 2007-01-23 at 20:31:53ID: 18382989

All,

I was trying not to bore everyone with a long post. But since I'm being told that what I'm doing is not possible, I feel the need to prove myself. I may not be an 'expert', but I'm no liar and I'm not retarded either.

Following is the VB6 code and output for 'Method#1' and 'Method#2'. I pointed at a small (seperate AND external) compiled VB6 application I threw together to test this code. As far as 'poor-security' goes, what can I say? I didn't write the Win32 API library! To repeat myself, the following output was generated from a seperately compiled executing 'EXE'. There's more code to my application. I tried to include only lines pertaining to this issue...

==========  Method #1 ============================================================

lRet = EnumChildWindows(p_oFormInfo(iIndex).hwnd, AddressOf EnumChildProc, lParam)  ' <<< hWnd of the ref'd form >>>
.
.
.
Function EnumChildProc(ByVal lhWnd As Long, ByVal lParam As Long) As Long
  Dim RetVal As Long, iIndex As Integer
  Dim WinClassBuf As String * 255, WinTitleBuf As String * 255
  Dim WinClass As String, WinTitle As String
  Dim lID As Long, lpRect As RECT
 
  RetVal = GetClassName(lhWnd, WinClassBuf, 255)
  WinClass = StripNulls(WinClassBuf)  ' remove extra Nulls & spaces
  RetVal = GetWindowText(lhWnd, WinTitleBuf, 255)
  WinTitle = StripNulls(WinTitleBuf)
     
  If GetWindowLong(lhWnd, GWW_ID) Then
    GetWindowRect lhWnd, lpRect
    lID = GetWindowLong(lhWnd, GWW_ID)
   
    iIndex = UBound(p_oControlInfo)
    ReDim Preserve p_oControlInfo(iIndex + 1)
    p_oControlInfo(iIndex).hwnd = lhWnd
    p_oControlInfo(iIndex).XLoc = lpRect.Left
    p_oControlInfo(iIndex).YLoc = lpRect.Top
    p_oControlInfo(iIndex).ID = lID
    p_oControlInfo(iIndex).Class = WinClass
    p_oControlInfo(iIndex).Title = WinTitle
   
    PPrint "Hwnd = " & p_oControlInfo(iIndex).hwnd & "  Class = " & p_oControlInfo(iIndex).Class & "  Title = '" & p_oControlInfo(iIndex).Title & "'  X-Loc = " & p_oControlInfo(iIndex).XLoc & "  Y-Loc = " & p_oControlInfo(iIndex).YLoc
  End If
  EnumChildProc = True
End Function
--------------------------------------------------------------------------------------------------------------------------------------

Hwnd = 3606330  Class = ThunderRT6Data  Title = 'DataNavigation'  X-Loc = 1251  Y-Loc = 482
Hwnd = 8259434  Class = ThunderRT6DriveListBox  Title = ''  X-Loc = 1251  Y-Loc = 610
Hwnd = 7604014  Class = ThunderRT6OptionButton  Title = 'Bottom Option'  X-Loc = 1251  Y-Loc = 738
Hwnd = 7014444  Class = ThunderRT6OptionButton  Title = 'Top Option'  X-Loc = 1251  Y-Loc = 714
Hwnd = 8587598  Class = ThunderRT6ListBox  Title = ''  X-Loc = 1387  Y-Loc = 682
Hwnd = 5376138  Class = ThunderRT6ComboBox  Title = ''  X-Loc = 1243  Y-Loc = 682
Hwnd = 13633778  Class = Edit  Title = ''  X-Loc = 1246  Y-Loc = 685
Hwnd = 1706164  Class = ThunderRT6CheckBox  Title = 'Right Check'  X-Loc = 1371  Y-Loc = 650
Hwnd = 10357056  Class = ThunderRT6CheckBox  Title = 'Left Check'  X-Loc = 1267  Y-Loc = 650
Hwnd = 5441768  Class = ThunderRT6Frame  Title = 'Frame1'  X-Loc = 1251  Y-Loc = 514
Hwnd = 4982842  Class = ThunderRT6CommandButton  Title = 'Frame Button'  X-Loc = 1395  Y-Loc = 562
Hwnd = 4917264  Class = ThunderRT6TextBox  Title = 'In the frame'  X-Loc = 1275  Y-Loc = 562
Hwnd = 3934264  Class = ThunderRT6OptionButton  Title = 'Option In Frame'  X-Loc = 1275  Y-Loc = 538
Hwnd = 3803230  Class = ThunderRT6CommandButton  Title = 'Open'  X-Loc = 1387  Y-Loc = 762
Hwnd = 9111828  Class = ThunderRT6CommandButton  Title = 'Exit'  X-Loc = 1243  Y-Loc = 762
Hwnd = 5572808  Class = ThunderRT6TextBox  Title = 'Johnson'  X-Loc = 1299  Y-Loc = 434
Hwnd = 6031502  Class = ThunderRT6TextBox  Title = 'Van'  X-Loc = 1299  Y-Loc = 402
Hwnd = 6883630  Class = ThunderRT6TextBox  Title = 'Daryl'  X-Loc = 1299  Y-Loc = 370

===============================================================================

==========  Method #2 ============================================================

lRet = GetWindowThreadProcessId(lhWnd, PID)  ' <<<< This is how I got the process ID I used...  >>>>
.
.
.
Sub GetVBProcessControls(oForm As clsForm, PID As Long)
    Dim hSnapshot   As Long
    Dim lRes        As Long
    Dim lRes2       As Long
    Dim tHL         As HEAPLIST32
    Dim tHE         As HEAPENTRY32
    Dim sProgID     As String
    Dim sObjName    As String
    Dim sCaption    As String

   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, PID)
   tHL.dwSize = Len(tHL)
   lRes = Heap32ListFirst(hSnapshot, tHL)
   With tHE
       Do While lRes = 1
          .dwSize = Len(tHE)
          lRes2 = Heap32First(tHE, tHL.th32ProcessID, tHL.th32HeapID)
          Do While lRes2 = 1
             If IsValidControl(tHE.dwBlockSize) Then
                sProgID = GetControlProgID(.th32ProcessID, .dwAddress)
                If IsValidClass(sProgID) Then
                   sObjName = GetControlName(tHL.th32ProcessID, .dwAddress)
                   sCaption = GetControlCaption(tHL.th32ProcessID, .dwAddress)
                   PPrint "   " & sProgID & ":   " & sObjName & ".Caption = '" & sCaption & "' [ " & .dwBlockSize & " ]"
                   If tHE.dwBlockSize = BSIZE_VB_Form Then
                     oForm.FormName = sObjName
                     oForm.Caption = sCaption
                   End If
                End If
             End If
             If oForm.FormNameOnly = True And sProgID = "VB.Form" Then Exit Do
             lRes2 = Heap32Next(tHE)
          Loop
          If oForm.FormNameOnly = True And sProgID = "VB.Form" Then Exit Do
          lRes = Heap32ListNext(hSnapshot, tHL)
       Loop
   End With
   CloseToolhelp32Snapshot hSnapshot
End Sub

Function GetControlCaption(ByVal PID As Long, ByVal BaseAddress As Long) As String
    Dim lStrPtr As Long, lInfoPtr As Long
   Toolhelp32ReadProcessMemory PID, BaseAddress + 136, lStrPtr, 4, 0
   GetControlCaption = String$(260, 0)
   If lStrPtr <> 0 Then
      Toolhelp32ReadProcessMemory PID, lStrPtr, ByVal GetControlCaption, 260, 4
   End If
   GetControlCaption = Left$(GetControlCaption, InStr(GetControlCaption, vbNullChar) - 1)
End Function

Function GetControlName(ByVal PID As Long, ByVal BaseAddress As Long) As String
    Dim lStrPtr As Long, lInfoPtr As Long
   Toolhelp32ReadProcessMemory PID, BaseAddress + 60, lInfoPtr, 4, 0
   Toolhelp32ReadProcessMemory PID, lInfoPtr + 4, lStrPtr, 4, 0
   GetControlName = String$(260, 0)
   If lStrPtr <> 0 Then
      Toolhelp32ReadProcessMemory PID, lStrPtr, ByVal GetControlName, 260, 0
   End If
   GetControlName = Left$(GetControlName, InStr(GetControlName, vbNullChar) - 1)
End Function
--------------------------------------------------------------------------------------------------------------------------------------

   VB.Form:   frmCaptureFrom.Caption = 'Capture From' [ 408 ]
   VB.Data:   dbDataNav.Caption = 'DataNavigation' [ 304 ]
   VB.DriveListBox:   drvMyList.Caption = '' [ 240 ]
   VB.OptionButton:   Option2.Caption = 'Bottom Option' [ 232 ]
   VB.OptionButton:   Option1.Caption = 'Top Option' [ 232 ]
   VB.ListBox:   lstMyList.Caption = '' [ 248 ]
   VB.ComboBox:   cboDropDown.Caption = 'Combo1' [ 280 ]
   VB.CheckBox:   chkRight.Caption = 'Right Check' [ 232 ]
   VB.CheckBox:   chkLeft.Caption = 'Left Check' [ 232 ]
   VB.Frame:   fraFrameContainer.Caption = 'Frame1' [ 224 ]
   VB.CommandButton:   cmdFrameButton.Caption = 'Frame Button' [ 232 ]
   VB.TextBox:   txtTextInFrame.Caption = 'In the frame' [ 256 ]
   VB.OptionButton:   optInFrame.Caption = 'Option In Frame' [ 232 ]
   VB.CommandButton:   Command1.Caption = 'Open' [ 232 ]
   VB.CommandButton:   cmdExit.Caption = 'Exit' [ 232 ]
   VB.TextBox:   txtLast.Caption = 'Johnson' [ 256 ]
   VB.TextBox:   txtMiddle.Caption = 'Van' [ 256 ]
   VB.TextBox:   txtFirst.Caption = 'Daryl' [ 256 ]
   VB.Label:   lblLast.Caption = 'Last:' [ 232 ]
   VB.Label:   lblMiddle.Caption = 'Middle:' [ 232 ]
   VB.Label:   lblFirst.Caption = 'First:' [ 232 ]
===============================================================================

I welcome 'helpful' and 'constructive' comments to this issue...

Thanks!

Warp

 

by: ArkPosted on 2007-01-25 at 01:07:03ID: 18393987

Function GetControlHwnd(ByVal PID As Long, ByVal BaseAddress As Long) As Long
   Toolhelp32ReadProcessMemory PID, BaseAddress + 64, GetControlHwnd, 4, 0
End Function

 

by: WarpNinePosted on 2007-01-25 at 07:16:12ID: 18395964

Hey Ark,

If you are a guy... YOU ARE DA MAN!!! If you are a chick... YOU GO GIRL!!!

That one freakin' line of code is EXACTLY what needed! Works beautifully! That was the last piece to this puzzle I’ve been pulling my hair out over! As you probably noticed from my last post, I was starting to get a little frustrated. People have been telling me for a week that what YOU just did could NOT be done.

I can’t thank you enough!!! Too bad I can’t give you more than ‘500xA’ points!!

You totally ROCK!!!

Thanks!

Warp

(P.S.: If you could point me where you found this information, it would be greatly appreciated!)

 

by: ArkPosted on 2007-01-28 at 15:52:59ID: 18416074

Hello
To tell the truth, when I read your question, I also didn't belive this is possible. But after you show your code I realized that only one person can play with VB objects such a way - I just googled for Toolhelp32ReadProcessMemory+morcillo and found source code at http://groups.google.ru/group/microsoft.public.vb.winapi/browse_thread/thread/fa4fa7425c830b7f/3d0a387af069aed6
The rest was trivial - main code is

If sObjName = "Label1" Then
   For i = 0 To 232 Step 4
       Toolhelp32ReadProcessMemory pid, tHE.dwAddress + i, lVal, 4, 0
       Debug.Print i, lVal, Hex(lVal)
   Next i
End If

Digging around structure I found following properties (Note: offsets snown are for Labels only. Seems first 208 offsets are equal for all controls while offsets greater then 208 may differ for other controls)
0-43 - Unknown (some pointers - probably, events handlers addresses?)
44 -    Class Info (pointer to Interface)
60 -    Object Info
64 -    hWnd
68,72 - seems to be a pointers to prev/next controls in form's controls collection
92 -    Left (twips)
96 -    Top (twips)
100 -   Width (twips)
104 -   Height (twips)
108 -   Left (pixels)
112 -   Top (pixels)
116 -   Back color
120 -   Fore color
128 - Unknown
132 - Tag (LPWSTR)
136 - Caption (LPSTR)
140 - DataField (LPSTR)
144 - DataMember (LPSTR)
148 - DataSource (LPSTR)
152 - DataFormat - Pointer to StdFormatObject
156,160 - Unknown
164 - WhatThisHelpID
168 - ToolTipText (LPSTR)
172 - DragIcon (hIcon)
176 - MouseIcon (hIcon)
180 - Pointer to DDE Link Object
184-192 - unknown
196 - TabIndex
200 - Unknown
204 - MousePointer (HiWord)
208 - Index (LoWord)
'==========For Label Only======
212 - Flags (Alignment, AutoSize etc) - See code below for flag values
216 - hFont (for form - 224)
228 - Seems to be more Flags (Appearance,Enabled, Visible) - not tested yet
Here is my sample (2 modules + 1 Form):

'============ mEnumWindows.bas========
'Purpose - Enumerate ThunderRT6... windows
Option Explicit

Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function EnumWindows& Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long)
Dim lb As ListBox

Function EnumWinProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
  If Left(GetWndClass(hWnd), 10) = "ThunderRT6" Then
     lb.AddItem GetWndText(hWnd)
     lb.ItemData(lb.NewIndex) = hWnd
  End If
  EnumWinProc = 1
End Function

Public Sub EnumVBWindows(lbWindows As ListBox)
  Set lb = lbWindows
  lb.Clear
  EnumWindows AddressOf EnumWinProc, 0
  Set lb = Nothing
End Sub

Private Function GetWndClass(hWnd As Long) As String
  Dim k As Long, sName As String
  sName = Space$(128)
  k = GetClassName(hWnd, sName, 128)
  If k > 0 Then sName = Left$(sName, k) Else sName = "No class"
  GetWndClass = sName
End Function

Private Function GetWndText(hWnd As Long) As String
  Dim k As Long, sName As String
  sName = Space$(128)
  k = GetWindowText(hWnd, sName, 128)
  If k > 0 Then sName = Left$(sName, k) Else sName = "No name"
  GetWndText = sName
End Function

'===============mEnumControls.bas=========
'Purpose - Enumerate controls and read their properties
Option Explicit

Const LF_FACESIZE = 32 'Font Dialog
Private Type LOGFONT 'Font Dialog
    lfHeight As Long
    lfWidth As Long
    lfEscapement As Long
    lfOrientation As Long
    lfWeight As Long
    lfItalic As Byte
    lfUnderline As Byte
    lfStrikeOut As Byte
    lfCharSet As Byte
    lfOutPrecision As Byte
    lfClipPrecision As Byte
    lfQuality As Byte
    lfPitchAndFamily As Byte
    lfFaceName(LF_FACESIZE) As Byte
End Type

Const TH32CS_SNAPHEAPLIST = &H1

Type HEAPLIST32
    dwSize As Long
    th32ProcessID As Long  ' owning process
    th32HeapID As Long     ' heap (in owning process's context!)
    dwFlags As Long
End Type


Type HEAPENTRY32
    dwSize As Long
    hHandle As Long        ' Handle of this heap block
    dwAddress As Long      ' Linear address of start of block
    dwBlockSize As Long    ' Size of block in bytes
    dwFlags As Long
    dwLockCount As Long
    dwResvd As Long
    th32ProcessID As Long  ' owning process
    th32HeapID As Long     ' heap block is in
End Type

Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal Flags As Long, ByVal pid As Long) As Long
Declare Function CloseToolhelp32Snapshot Lib "kernel32" Alias "CloseHandle" (ByVal Handle As Long) As Long
Declare Function Heap32ListFirst Lib "kernel32" (ByVal hSnapshot As Long, lphl As HEAPLIST32) As Long
Declare Function Heap32ListNext Lib "kernel32" (ByVal hSnapshot As Long, lphl As HEAPLIST32) As Long
Declare Function Heap32First Lib "kernel32" (lphe As HEAPENTRY32, ByVal th32ProcessID As Long, ByVal th32HeapID As Long) As Long
Declare Function Heap32Next Lib "kernel32" (lphe As HEAPENTRY32) As Long
Declare Function Toolhelp32ReadProcessMemory Lib "kernel32" (ByVal th32ProcessID As Long, ByVal lpBaseAddress As Long, lpBuffer As Any, ByVal cbRead As Long, lpNumberOfBytesRead As Long) As Long
Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetObj Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cBytes As Long)

Dim cb As ComboBox

Public Function EnumVBControls(ByVal hForm As Long, cbControls As ComboBox)
   Dim hSnapshot As Long
   Dim lRes As Long, lRes2 As Long, idx As Long
   Dim pid As Long, tid As Long
   Dim tHL As HEAPLIST32
   Dim tHE As HEAPENTRY32
   Dim lf As LOGFONT
   
   Dim sProgid As String, sObjName As String, sShortProgID As String, s As String
   
   Dim i As Long, lVal As Long, lVal1 As Long
   Dim sCaption As String
   Dim bDone As Boolean
   tid = GetWindowThreadProcessId(hForm, pid)  ' Get ProcessID
   If pid = 0 Then Exit Function
   Set cb = cbControls
   cb.Clear
   cb.Tag = pid
'   cb.Sorted = True
   
   ' Create a snapshot of the process
   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, pid)
   tHL.dwSize = Len(tHL)
   ' Find first heap
   lRes = Heap32ListFirst(hSnapshot, tHL)
   Do While lRes = 1
      tHE.dwSize = Len(tHE)
      ' Find first heap
      lRes2 = Heap32First(tHE, tHL.th32ProcessID, tHL.th32HeapID)
      Do While lRes2 = 1
         If ValidateSize(tHE.dwBlockSize) Then
            sProgid = GetControlProgID(tHE.th32ProcessID, tHE.dwAddress)
            sShortProgID = ShortProgID(sProgid)
            If sShortProgID <> "" Then
               sObjName = GetControlName(tHL.th32ProcessID, tHE.dwAddress)
               idx = GetIndex(pid, tHE.dwAddress)
               If idx > -1 Then
                  sObjName = sObjName & "(" & idx & ")"
               End If
               cb.AddItem sObjName & "    [" & sShortProgID & "]"
               cb.ItemData(cb.NewIndex) = tHE.dwAddress
'================ For testings========================================
If sObjName = "Label1" Then
   For i = 0 To 232 Step 4
       Toolhelp32ReadProcessMemory pid, tHE.dwAddress + i, lVal, 4, 0
       Debug.Print i, lVal, Hex(lVal)
   Next i
End If
'=====================================================================
            End If
         End If
         lRes2 = Heap32Next(tHE)
      Loop
       ' Find next heap
      lRes = Heap32ListNext(hSnapshot, tHL)
   Loop
   ' Close the snapshot
   CloseToolhelp32Snapshot hSnapshot
   Set cb = Nothing
End Function

Function GetControlProgID(ByVal pid As Long, ByVal BaseAddress As Long) As String
   Dim lInfoPtr As Long
   Dim lStrPtr As Long

   ' Get pointer to class info
   Toolhelp32ReadProcessMemory pid, BaseAddress + 44, lInfoPtr, 4, 0
   ' Get pointer to sProgID string
   Toolhelp32ReadProcessMemory pid, lInfoPtr + 36, lStrPtr, 4, 0
   ' Get control ProgID
   GetControlProgID = String$(260, 0)
   If lStrPtr <> 0 Then
      Toolhelp32ReadProcessMemory pid, lStrPtr, ByVal GetControlProgID, 260, 0
   End If
   GetControlProgID = TrimNULL(GetControlProgID)
End Function

Function GetControlName(ByVal pid As Long, ByVal BaseAddress As Long) As String
   Dim lStrPtr As Long
   Dim lInfoPtr As Long
   ' Get pointer to object info
   Toolhelp32ReadProcessMemory pid, BaseAddress + 60, lInfoPtr, 4, 0
   ' Get pointer to object name
   Toolhelp32ReadProcessMemory pid, lInfoPtr + 4, lStrPtr, 4, 0
   ' Get object name
   GetControlName = String$(260, 0)
   If lStrPtr <> 0 Then
      Toolhelp32ReadProcessMemory pid, lStrPtr, ByVal GetControlName, 260, 0
   End If
   GetControlName = TrimNULL(GetControlName)
End Function

Public Function GetControlProperty(ByVal pid As Long, ByVal BaseAddress As Long, _
                                   ByVal Offset As Long, ByVal sType As String, _
                                   Optional ByVal bitNum As String, _
                                   Optional ByVal bitNames As String) As Variant
   Dim lVal As Long, lVal1 As Long, i As Long
   Dim s As String
   Dim lf As LOGFONT
   Dim varBitNums As Variant
   Dim varBitNames As Variant
   Dim abData() As Byte, abTemp() As Byte
   Dim intData As Integer
   
   If UCase(sType) = "NAME" Then
      GetControlProperty = GetControlName(pid, BaseAddress)
      Exit Function
   End If
   GetControlProperty = ""
   Toolhelp32ReadProcessMemory pid, BaseAddress + Offset, lVal, 4, 0
   Select Case UCase(sType)
      Case "DWORD":  GetControlProperty = lVal
      Case "HEX":  GetControlProperty = "&H" & Right("00000000" & Hex(lVal), 8)
      Case "LOWORD": GetControlProperty = LoWord(lVal)
      Case "HIWORD": GetControlProperty = HiWord(lVal)
      Case "LPSTR", "LPWSTR"
           If lVal = 0 Then Exit Function
           s = String$(260, 0)
           Toolhelp32ReadProcessMemory pid, lVal, ByVal s, 260, 0
           If bitNum <> "" Then s = Mid(s, CLng(bitNum))
           If sType = "LPWSTR" Then s = StrConv(s, vbFromUnicode)
           GetControlProperty = TrimNULL(s)
      Case "FONT"
         If lVal = 0 Then Exit Function
         If UCase(GetControlProgID(pid, BaseAddress)) = "VB.FORM" Then
            Toolhelp32ReadProcessMemory pid, BaseAddress + Offset + 8, lVal, 4, 0
         End If
         GetObj lVal, Len(lf), lf
         GetControlProperty = TrimNULL(StrConv(lf.lfFaceName, vbUnicode))
      Case "LINKOBJECT"
           If lVal = 0 Then Exit Function
           ReDim abData(259)
           Toolhelp32ReadProcessMemory pid, lVal, abData(0), 260, 0
           lVal = 0
           Select Case UCase(bitNum)
               Case "ITEM"
                    ReDim abTemp(259)
                    CopyMemory abTemp(0), abData(28), 200
                    s = StrConv(abTemp, vbUnicode)
                    lVal = InStr(1, s, Chr(0))
                    If lVal > 0 Then s = Mid(s, lVal + 10)
               Case "MODE"
               Case "SOURCE"
               Case "TIMEOUT"
                    CopyMemory lVal, abData(14), 2
                    s = lVal
               Case "TOPIC"
                    ReDim abTemp(259)
                    CopyMemory abTemp(0), abData(28), 200
                    s = StrConv(abTemp, vbUnicode)
           End Select
           GetControlProperty = TrimNULL(s)
      Case "DATAFORMAT"
           If lVal = 0 Then Exit Function
           Toolhelp32ReadProcessMemory pid, lVal + 8, lVal, 4, 0
           Toolhelp32ReadProcessMemory pid, lVal + 80, lVal1, 4, 0
           Select Case lVal1
              Case 0: s = "General"
              Case 1
                   Toolhelp32ReadProcessMemory pid, lVal + 92, lVal1, 4, 0
                   Select Case lVal1
                      Case 1:  s = "Number"
                      Case 2:  s = "Percentage"
                      Case 7:  s = "Time"
                      Case 9:  s = "Scientific"
                      Case 10: s = "Time"
                      Case 12: s = "Currency"
                      Case Else: s = "Custom"
                   End Select
              Case 2: s = "Picture"
              Case 3: s = "Object"
              Case 4: s = "Checbox"
              Case 5: s = "Boolean"
              Case 6: s = "Bytes"
              Case Else: s = "Unknown"
           End Select
           GetControlProperty = s
      Case "ICON"
           If lVal = 0 Then GetControlProperty = "(None)" Else GetControlProperty = "(Icon)"
      Case "FLAG"
           If bitNum = "" Then Exit Function
           varBitNums = Split(bitNum, ",")
           varBitNames = Split(bitNames, ",")
           For i = 0 To UBound(varBitNums)
               If (lVal And varBitNums(i)) Then
                  s = varBitNames(i)
                  Exit For
               End If
           Next i
           If s = "" Then s = varBitNames(UBound(varBitNames))
           GetControlProperty = s
      Case Else
   End Select
End Function

Private Function ValidateSize(ByVal iSize As Long) As Boolean
   ValidateSize = True
   Select Case iSize
       Case 224 'Frame
       Case 232 'label,command button, checkbox, option button
       Case 248 'array of controls (including menu and list box)
       Case 256 'textbox
       Case 280 'combobox
       Case 328 'picturebox
       Case 376 'WebBrowser, Common controls, DataList/Combo
       Case 408 'Form
       Case Else
            ValidateSize = False
   End Select
End Function

Private Function ShortProgID(ByVal sProgid As String) As String
   Dim nPos As Long
   nPos = InStr(1, sProgid, ".")
   If nPos = 0 Then Exit Function
   Select Case sProgid
       Case "VB.Menu", "VB.Printer", "VB.Clipboard"
       Case Else: ShortProgID = Mid(sProgid, nPos + 1)
   End Select
End Function

Private Function GetIndex(ByVal pid As Long, ByVal BaseAddress As Long) As Long
   Dim lVal As Long, idx As Long
   Toolhelp32ReadProcessMemory pid, BaseAddress + 208, lVal, 4, 0
   GetIndex = LoWord(lVal)
End Function

Public Function TrimNULL(ByVal str As String) As String
    If InStr(str, Chr$(0)) > 0& Then
        TrimNULL = Left$(str, InStr(str, Chr$(0)) - 1&)
    Else
        TrimNULL = str
    End If
End Function

Public Function LoWord(ByVal dw As Long) As Integer
    If dw And &H8000& Then
        LoWord = dw Or &HFFFF0000
    Else
        LoWord = dw And &HFFFF&
    End If
End Function

Public Function HiWord(ByVal dw As Long) As Integer
    HiWord = (dw And &HFFFF0000) \ 65536
End Function

'===========Form code=======
'Add Listbox (Name=lbWindows), ComboBox (cbControls) and ListView(lvPropertis) on form - any size, any position
'Copy/Paste following code:
Option Explicit

Private Sub cbControls_Click()
   EnumProperties
End Sub

Private Sub Form_Load()
   Caption = "VB controls demo"
   Width = 8700
   With lvProperties
      .View = lvwReport
      .ColumnHeaders.Clear
      .ColumnHeaders.Add , , "Property", 2000
      .ColumnHeaders.Add , , "Value", 1900
      .Appearance = ccFlat
      .FullRowSelect = True
      .GridLines = True
      .LabelEdit = lvwManual
   End With
   FillPropertiesNames
   EnumVBWindows lbWindows
   Show
'   If lbWindows.ListCount Then lbWindows.ListIndex = 0
End Sub

Private Sub Form_Resize()
   lbWindows.Move 60, 60, ScaleWidth / 2 - 120, ScaleHeight - 120
   cbControls.Move ScaleWidth / 2, 60, ScaleWidth / 2 - 60
   lvProperties.Move cbControls.Left, cbControls.Top + cbControls.Height + 60, cbControls.Width
   lvProperties.Height = ScaleHeight - lvProperties.Top - 60
End Sub

Private Sub lbWindows_Click()
   MousePointer = vbHourglass
   DoEvents
   EnumVBControls lbWindows.ItemData(lbWindows.ListIndex), cbControls
   If cbControls.ListCount Then cbControls.ListIndex = 0
   MousePointer = vbDefault
End Sub

Private Sub FillPropertiesNames()
   lvProperties.ListItems.Clear
   AddProperty "(Name)", "60", "NAME"
   AddProperty "Alignment", "212", "FLAG", "4,2", "2 - Center,1 - Right Justify,0 - Left Justify"
   AddProperty "Appearance", "212", "FLAG"
   AddProperty "AutoSize", "212", "FLAG", "1", "True,False"
   AddProperty "BackColor", "116", "HEX"
   AddProperty "BackStyle", "212", "FLAG", "16", "1 - Opaque,0 - Transparent"
   AddProperty "BorderStyle", "212", "FLAG", "32", "1 - Fixed Single,0 - None"
   AddProperty "Caption", "136", "LPSTR"
   AddProperty "DataField", "140", "LPSTR"
   AddProperty "DataFormat", "152", "DATAFORMAT"
   AddProperty "DataMember", "144", "LPSTR"
   AddProperty "DataSource", "148", "LPSTR"
   AddProperty "DragIcon", "172", "ICON"
   AddProperty "DragMode", "0", "UNKNOWN"
   AddProperty "Enabled", "212", "FLAG"
   AddProperty "Font", "216", "FONT"
   AddProperty "ForeColor", "120", "HEX"
   AddProperty "Height", "104", "DWORD"
   AddProperty "Index", "208", "LOWORD"
   AddProperty "Left", "92", "DWORD"
   AddProperty "LinkItem", "180", "LINKOBJECT", "ITEM"
   AddProperty "LinkMode", "0", "UNKNOWN"
   AddProperty "LinkTimeout", "180", "LINKOBJECT", "TIMEOUT"
   AddProperty "LinkTopic", "180", "LINKOBJECT", "TOPIC"
   AddProperty "MouseIcon", "176", "ICON"
   AddProperty "MousePointer", "204", "HIWORD"
   AddProperty "OLEDropMode", "0", "UNKNOWN"
   AddProperty "RightToLeft", "212", "FLAG"
   AddProperty "TabIndex", "196", "DWORD"
   AddProperty "Tag", "132", "LPWSTR"
   AddProperty "ToolTipText", "168", "LPSTR"
   AddProperty "Top", "96", "DWORD"
   AddProperty "UseMnemonic", "212", "FLAG", "64", "True,False"
   AddProperty "Visible", "0", "UNKNOWN"
   AddProperty "WhatsThisHelpID", "164", "DWORD"
   AddProperty "Width", "100", "DWORD"
   AddProperty "WordWrap", "212", "FLAG", "8", "True,False"
End Sub

Private Sub AddProperty(ByVal sName As String, ByVal sOffset As String, _
                        ByVal sType As String, _
                        Optional bitNum As String, _
                        Optional bitName As String)
   sType = sOffset & "_" & sType
   If bitNum <> "" Then sType = sType & "_" & bitNum
   If bitName <> "" Then sType = sType & "_" & bitName
   lvProperties.ListItems.Add(, , sName).Tag = sType
End Sub

Private Sub EnumProperties()
   Dim li As Object
   Dim varData As Variant
   Dim iOffset As Long, bitNum As Long
   Dim sType As String, s As String
   For Each li In lvProperties.ListItems
      varData = Split(li.Tag, "_")
      Select Case UBound(varData)
         Case 1
              s = GetControlProperty(cbControls.Tag, cbControls.ItemData(cbControls.ListIndex), varData(0), varData(1))
         Case 2
              s = GetControlProperty(cbControls.Tag, cbControls.ItemData(cbControls.ListIndex), varData(0), varData(1), varData(2))
         Case 3
              s = GetControlProperty(cbControls.Tag, cbControls.ItemData(cbControls.ListIndex), varData(0), varData(1), varData(2), varData(3))
         Case Else: s = "Invalid Type"
      End Select
      If (li.Text = "Index") And (s = "-1") Then s = ""
      li.SubItems(1) = s
   Next
End Sub

Regards
Ark

 

by: ArkPosted on 2007-01-28 at 16:00:29ID: 18416098

PS
>>If you are a guy<< Yes :)

 

by: WarpNinePosted on 2007-01-28 at 17:03:36ID: 18416290


Like I said before... YOU TOTALLY ROCK!!! DUDE!!!

I'm going to be picking off of this code for weeks. You're making me appear to be VERY smart!

Thanks again!

Warp

 

by: ArkPosted on 2007-01-28 at 21:33:03ID: 18417046

More amazing - you can change another process properties on the fly!
Add following declarations to mEnumControls.bas:

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function MulDiv Lib "kernel32" (ByVal nNumber As Long, ByVal nNumerator As Long, ByVal nDenominator As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function CreateFontIndirect Lib "gdi32" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long

Const MEM_COMMIT = &H1000
Const MEM_RESERVE = &H2000
Const MEM_RELEASE = &H8000

Const PAGE_READWRITE = &H4&
Const PAGE_EXECUTE_READWRITE = &H40&
Const PROCESS_ALL_ACCESS = &H1F0FFF
Public hFont As Long, hDragIcon As Long, hMouseIcon As Long

'Add Follofing functions also:

Public Function SetControlProperty(ByVal pid As Long, ByVal BaseAddress As Long, _
                                   ByVal Offset As Long, ByVal sType As String, _
                                   ByVal varValue As Variant) As Boolean
   Dim hProcess As Long, lVal As Long, ret As Long, addr As Long, oldProtect As Long
   Dim intVal As Integer
   Dim s As String
   hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
   Select Case sType
      Case "DWORD"
           lVal = CLng(varValue)
           WriteProcessMemory hProcess, ByVal BaseAddress + Offset, lVal, 4, ret
      Case "HEX"
           lVal = CLng(Val(varValue))
           WriteProcessMemory hProcess, ByVal BaseAddress + Offset, lVal, 4, ret
      Case "LOWORD"
           intVal = CInt(varValue)
           WriteProcessMemory hProcess, ByVal BaseAddress + Offset, intVal, 2, ret
      Case "HIWORD"
           intVal = CInt(varValue)
           WriteProcessMemory hProcess, ByVal BaseAddress + Offset + 2, intVal, 2, ret
      Case "LPSTR", "LPWSTR"
           s = CStr(varValue)
           If sType = "LPWSTR" Then s = StrConv(s, vbUnicode)
           addr = VirtualAllocEx(hProcess, 0, Len(s), MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
           If addr Then
              WriteProcessMemory hProcess, ByVal addr, ByVal s, Len(s), ret
              WriteProcessMemory hProcess, ByVal BaseAddress + Offset, addr, 4, ret
           End If
      Case "FONT"
           lVal = CLng(varValue)
           WriteProcessMemory hProcess, ByVal BaseAddress + Offset, lVal, 4, ret
      Case "LINKOBJECT"
      Case "DATAFORMAT"
      Case "ICON"
           lVal = CLng(varValue)
           WriteProcessMemory hProcess, ByVal BaseAddress + Offset, lVal, 2, ret
      Case "FLAG"
           lVal = CLng(varValue)
           WriteProcessMemory hProcess, ByVal BaseAddress + Offset, lVal, 4, ret
      Case Else
   End Select
   CloseHandle hProcess
   SetControlProperty = CBool(ret)
End Function


Public Function ShowFontDialog(cdlg As CommonDialog) As Long
   Dim lf As LOGFONT
   Dim tmpArr() As Byte
  Dim i As Integer, lArr As Long
   GetObj hFont, Len(lf), lf
   With cdlg
        .Flags = cdlCFBoth
        .FontBold = (lf.lfWeight > 400)
        .FontItalic = lf.lfItalic
        .FontName = StrConv(lf.lfFaceName, vbUnicode)
        .FontSize = -MulMul(lf.lfHeight, GetDeviceCaps(GetDC(0), 90&), 72)
        .FontStrikethru = lf.lfStrikeOut
        .FontUnderline = lf.lfUnderline
        .CancelError = True
        On Error Resume Next
        If Err Then Exit Function
        .ShowFont
        lf.lfHeight = -MulDiv(.FontSize, GetDeviceCaps(GetDC(0), 90&), 72)
        lf.lfItalic = Abs(.FontItalic)
        lf.lfStrikeOut = Abs(.FontStrikethru)
        lf.lfUnderline = Abs(.FontUnderline)
        lf.lfWeight = IIf(.FontBold, 700, 400)
        tmpArr = StrConv(.FontName & Chr$(0), vbFromUnicode)
        lArr = UBound(tmpArr)
        For i = 0 To lArr
            lf.lfFaceName(i) = tmpArr(i)
        Next i
        hFont = CreateFontIndirect(lf)
   End With
   ShowFontDialog = hFont
End Function

Private Function MulMul(arg1 As Long, arg2 As Long, arg3 As Long) As Integer
   Dim tmp As Single
   tmp = arg2 / arg3
   tmp = arg1 / tmp
   MulMul = CInt(tmp)
End Function

'Add common dialog control on form.
'And finally add following event handler on form:

Private Sub lvProperties_ItemClick(ByVal Item As MSComctlLib.ListItem)
   Dim varData As Variant, varValue As String, sType As String
   Dim pid As Long, BaseAddress As Long, iOffset As Long
   Dim sFont As StdFont
   pid = cbControls.Tag
   BaseAddress = cbControls.ItemData(cbControls.ListIndex)
   varData = Split(Item.Tag, "_")
   iOffset = varData(0)
   sType = varData(1)
   Select Case UCase(sType)
      Case "FONT"
          varValue = ShowFontDialog(CommonDialog1)
          SetControlProperty pid, BaseAddress, iOffset, sType, varValue
      Case Else
          varValue = InputBox("EnterNewValue for " & Item.Text, "Change property", Item.SubItems(1))
          SetControlProperty pid, BaseAddress, iOffset, sType, varValue
   End Select
   cbControls_Click
End Sub

'Now, you can change any property. For example, to change BackColor for label, just click on appropriate property and type &HFF in inputbox, press OK - you'll get red back color. To cahge font - click on font property and change font values in common dialog. I didn't apply code for Icons, Flags etc, but its not too difficult. It's even possible to make same property windows like in VB IDE for remote process!

 

by: stickleprojectsPosted on 2008-02-21 at 23:10:31ID: 20955237

All
If you use heapwalk instead of heap32next it is much much quicker (seconds instead of minutes)
I'll drop the code on here, if that's ok?

Private Declare Function GetProcessHeaps Lib "kernel32" ( _
    ByVal NumberOfHeaps As Long, ProcessHeaps As Long) As Long
 
 
Private Declare Function HeapWalk Lib "kernel32" ( _
    ByVal hHeap As Long, lpEntry As PROCESS_HEAP_ENTRY) As Long
 
 
Private Type PROCESS_HEAP_ENTRY
  lpData As Long
  cbData As Long
  cbOverhead As Byte
  iRegionIndex As Byte
  wFlags As Integer
  dwCommittedSize As Long
  dwUnCommittedSize As Long
  lpFirstBlock As Long
  lpLastBlock As Long
End Type
 
 
Private Const PROCESS_HEAP_REGION As Integer = &H1
Private Const PROCESS_HEAP_UNCOMMITTED_RANGE As Integer = &H2
Private Const PROCESS_HEAP_ENTRY_BUSY As Integer = &H4
Private Const PROCESS_HEAP_ENTRY_MOVEABLE As Integer = &H10
Private Const PROCESS_HEAP_ENTRY_DDESHARE As Integer = &H20
 
Public Sub DoHeapWalk(thHeapID As Long)
    Dim tHeap As PROCESS_HEAP_ENTRY
    tHeap.lpData = 0
    
    
    Do While HeapWalk(thHeapID, tHeap)
         If ValidateSize(tHeap.cbData + tHeap.cbOverhead) Then
            ......
         End If
    Loop
    
End Sub

                                              
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:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:

Select allOpen in new window

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...