Solved

SAFELY removing desktop icons in VBA???

Posted on 2000-05-03
8
223 Views
Last Modified: 2013-12-18
Hi folks,

Sorry about the length of the question.

I have a program that interrogates the desktop.dsk file for references to hierarchical servers (should be flat in our organisation).

Once found, the path and server names are extracted and a list made.

I then open Notes, use the AddDatabase method to add each database to the workspace, and then simulate a FileDatabaseRemove to remove it from the workspace using the keybd_event API call (e.g. Alt key down, Alt key up, E key pressed, E key released, L key down, L key up, Enter key down, Enter key up - this removes a database icon using Enter to answer Yes to prompt).

Notes is then closed and restarted.

Once restarted, the deleted icons are added back onto the workspace without the hierarchical references to the servernames.

It is a somewhat dangerous practice to be using the keybd_event API call since if a database cannot be removed and one is not selected then the workspace page would be removed instead.

I need to find a SAFE way to either catch the prompts that Notes supplies to users (e.g. Are you sure you wish to remove this database icon?, identify the message prompt and perform an action accordingly.

Can anyone help?

Thanks in advance,

Scott.
0
Comment
Question by:Scott2000
  • 4
  • 4
8 Comments
 
LVL 3

Expert Comment

by:Simon_Hendry
ID: 2775613
The best way to do this I think it to check for the existince of a window that's title is the error message your are looking for and the windows parent is the error message window.. If you find the window then you can then find the two buttons "Yes" and "No" on the window and click either one depending on what you want to do

To elaborate:

You can use the GetClassName API , GetWindowText API , GetDesktop Window API and PostMessage API

When My Notes V4.6.2 Displays a message it uses a window of class
"#32770" with window text "Lotus Notes" this window has three child windows.

1 . A window of class "static" thats window title is the error message , for example "This operation will remove the workspace page?. Are you sure you wish to proceed"

2. A Window of Class "Button" with title "Yes"

3. A Window of Class "Button" with title "No"

So what I would need to do it run your code to remove the icon and then use the FindWindowLike function ( below) to find  the window handle to the window that is of Class  "Static" and has a windowtitle of either "remove selected icon(s) from your desktop?" or  "This operation will delete the selected workspace page. Are you sure you would like to proceed?"

Depending on which window you find will tell you what operation has been performed. So depending on the message you find you can then use the GetParent API to find that windows parent. And then again use the findwindow function to find either the "Yes" or the "No" button (depending on which one you want to press). As you are looking for a button this time you will probably find quite a number so you need to find the button who's parent windowID (GetParent API returns this) is the also the parent of the "static" you found containing the error message. Once you have found the button "handle" you can then press it using the code::

Public Const BM_SETSTATE = &HF3
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONUP = &H202
Public Const WM_MOUSEMOVE = &H200

Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Call PostMessage(Handle, WM_MOUSEMOVE, 0, 1)
Call PostMessage(Handle, WM_LBUTTONDOWN, 0, 0)
Call PostMessage(Handle, BM_SETSTATE, 1, 1)
Call PostMessage(Handle, WM_LBUTTONUP, 0, 0)
Call PostMessage(Handle, BM_SETSTATE, 0, 0)



And the code to find any window on the system is :::

Declare Function GetDesktopWindow Lib "user32" () As Long
Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long

Public Const GW_CHILD = 5
Public Const GW_HWNDNEXT = 2

 Function FindWindowLike(hWndArray() As Long, ByVal hWndStart As Long, WindowText As String, Classname As String, ID) As Long
   Dim hwnd As Long
   Dim r As Long
   Static level As Long
   Static iFound As Long
   Dim sWindowText As String
   Dim sClassname As String
 
      ' Initialize if necessary:
   If level = 0 Then
       
        iFound = 0
        ReDim hWndArray(0 To 0)
        If hWndStart = 0 Then hWndStart = GetDesktopWindow()
 
   End If
   
   level = level + 1
   
   hwnd = GetWindow(hWndStart, GW_CHILD)
   
   Do Until hwnd = 0
   
   r = FindWindowLike(hWndArray(), hwnd, WindowText, Classname, ID)
   sWindowText = Space(255)
   r = GetWindowText(hwnd, sWindowText, 255)
   sWindowText = Left(sWindowText, r)
   sClassname = Space(255)
   r = GetClassName(hwnd, sClassname, 255)
   sClassname = Left(sClassname, r)
     
   ' Check that window matches the search parameters:
   If Classname = "*" Then
   
        If Trim(sWindowText) = Trim(WindowText) Then
   
         iFound = iFound + 1
         ReDim Preserve hWndArray(0 To iFound)
         hWndArray(iFound) = hwnd
       
        End If
       
  Else
   
   If Trim(sWindowText) = Trim(WindowText) And Trim(sClassname) = Trim(Classname) Then
     
     iFound = iFound + 1
     ReDim Preserve hWndArray(0 To iFound)
     hWndArray(iFound) = hwnd
   
   End If
   
  End If
   ' Get next child window:
   hwnd = GetWindow(hwnd, GW_HWNDNEXT)
   Loop
   ' Decrement recursion counter:
   level = level - 1
   ' Return the number of windows found:
   FindWindowLike = iFound
   
   End Function



What program are you using to interegate the desktop.dsk file ???

0
 
LVL 3

Accepted Solution

by:
Simon_Hendry earned 300 total points
ID: 2775642
PS .. If you want to find out about windows names and classes then you should get a copy of spyxx.exe  , if you can't find one on the net I can e-mail you a copy...

And I also forgot this bit..

Dim ParentHandle As Long
Dim Windows() As Long
Dim NoofReturnedWindows As Long
Dim r As Long
Dim sWindowText As String
Dim sClassname As String

Set NoofReturnedWindows = FindWindowLike(Windows(),0, "remove selected icon(s) from your desktop?","Static", 0)

If NoofReturnedWindows <> 0 Then

For i = i to NoofReturnedWindows

 ParentHandle=GetParent(Windows(i))

  sWindowText = Space(255)
  r = GetWindowText(ParentHandle, sWindowText, 255)
  sWindowText = Left(sWindowText, r)
 
  sClassname = Space(255)
  r = GetClassName(ParentHandle, sClassname, 255)
  sClassname = Left(sClassname, r)

  MsgBox "The Parent of the Error Windows Title is " + sWindowText
  MsgBox "The Parent of the Error Windows Class is " + sClassName

Next i

End if
0
 

Author Comment

by:Scott2000
ID: 2776690
Hi Simon,

Thanks for the information.  I will investigate this when I get a spare chance and get back to you.

Does your proposing an answer instead of adding a comment lock out other people from adding comments?

Cheers,

Scott.
0
 
LVL 3

Expert Comment

by:Simon_Hendry
ID: 2776699
No other people can add comments
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:Scott2000
ID: 2776806
Hi Simon,

I am using grepfv10.exe to perform a text search of the desktop file looking for test strings matching my criteria.

As far as I can tell, there is no functionality exposed or program available that will properly interrogate the desktop.

Yes you can open the desktop.dsk as a database on your workspace the same way you open any other database, but it only shows you the private views that are stored in your desktop file.  Not much use when you need to replace icons etc.

Thanks again,

Scott.
0
 

Author Comment

by:Scott2000
ID: 2776977
I will reject your answer to allow other input, but still need to check whether your answer is good.

Cheers,

Scott.

0
 
LVL 3

Expert Comment

by:Simon_Hendry
ID: 2777166
You didn't have to reject my answer to let other people add comments, but it doesn't really matter...

Re your other points.. There is in fact NO API to remove a desktop icon, in notes 4.X in any toolkit I have found..

So if you get ALL of the code to work , you should probably post it to notes.net or something similar , because there may well be a few people out there who would be keen to check it out....
0
 

Author Comment

by:Scott2000
ID: 2825495
Hi Simon,

I have modified your code quite a bit, but the initial API calls etc have came from you, so here's your points!

Thanks,

Scott.

p.s. know anyway to run a workspace compact from a vba program?  I am going to look at activating the appropriate window etc, but not promising...
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

You’ve got a lotus Domino web server, and you have been told that “leverage browser caching” is a must do. This means that we have to tell the browser everywhere in the web to use cache. In other words, we set (and send) an expiration date in the HT…
Lack of Storage capacity is a common problem that exists in every field of life. Here we are taking the case of Lotus Notes Emails, as we all know that we are totally depend on e-communication i.e. Emails. This article is fully dedicated to resolvin…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now