Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / WinForm General / June 2007

Tip: Looking for answers? Try searching our database.

hide cursor for kiosk application (powerpoint)

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
lockness - 14 May 2007 15:39 GMT
I'm developing a kiosk app in vb2005 and don't want the mouse pointer
to shown.

I'm using the webbrower control to display documents of various types.
eg PDF and Powerpoint. I simply pass the document location via  
me.webbrowser.navigate("file://...") and the webbrowser works out which
application it then has to call (Acrobat or Powerpoint) to display
the document within the browser window.

This works well for PDFs, Powerpoint seems to be a law unto itself.
Firstly I needed to set a registry value to force it into windowed mode:

rkPPT = Registry.ClassesRoot.CreateSubKey("PowerPoint.Show.8")
rkPPT.SetValue("BrowserFlags", 0, RegistryValueKind.DWord)

Now I discover that powerpoint does not obey the cursor.hide settings.
(whereas acrobat does)

As a test I set a button.click event to set cursor.hide. But as soon as I
click
into the powerpoint slide the cursor comes back.

I've seen references to the low level ShowCursor function. Is this what I'll
have to do ?

As a side issue I've found Powerpoint to be a pain to work with.
Looking at the MSDN developer centre for Powerpoint I found
that it's appears to be centred around PP2003 not PP2007.
Whereas for Windows Media Player I found great documentation
explaining how to interop from .NET, for PP it's all VBA related.

M.
Linda Liu [MSFT] - 15 May 2007 12:17 GMT
Hi,

Based on my understanding, you use a WebBrowser control to display
PowerPoint document and you'd like to hide the cursor on the WebBrowser. If
I'm off base, please feel free to let me know.

I have spent several hours on this issue but haven't found a solution yet.

In my test, I call the Cursor.Hide method to  hide the cursor. When I move
the pointer on the WebBrowser, I did see that the cursor comes back.

I use Spy++ to watch the application, and see that there're several child
windows in the WebBrowser. The class and window names of these child
windows are as follows:
Shell Embedding ""
 Shell DocObject View ""
    childClass ""
        childClass "PowerPoint Slide
Show-[PPT1.ppt[Read-Only][Compatibility Mode]]"
           paneClassDC "Slide Show"

I watch the messages of the paneClassDC "Slide Show" window. When I move
the pointer on the WebBrowser, Spy++ catches the WM_SETCURSOR and
WM_MOUSEMOVE messages.

It seems that it's the paneClassDC "Slide Show" window that captures the
cursor and show it.

I have managed to get the handle of the paneClassDC window, but I haven't
worked out how to prevent the paneClassDC window from showing the cursor
until now.

BTW, could you tell me why you'd like to hide the cursor on the WebBrowser
when displaying PowerPoint document?

I will go on the research and will get the result back to you ASAP.

I appreciate your patience!

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
lockness - 15 May 2007 13:30 GMT
Hi LL

The app is to run on a kiosk with a touchscreen. There is no mouse control.
When the user touches the screen this is equivalent to a mouse click.
It does not look good to have a mouse pointer on screen in this situation.

You do seem to have recreated the problem correctly.

I'm new to windows development and the associated tools.
I've just been experimenting with spy++ myself for a related problem
using powerpoint via interop instead of the webbrowser control.

You mention in your reply you were able to get the handle of the slideshow:
paneClassDC "Slide Show"

This is exactly what I've been trying for the last few hours so I can
then use the handle with SetForegroundWindow(hndl) to ensure the slideshow
is on top.

So far my attempts with  hndl = FindWindow("paneClassDC", "Slide Show")
and other variations have failed. If you could explain how you got the
handle that would greatly help although I realize it's a differrent issue to
the one I've raised.

Thanks

M.

> Hi,
>
[quoted text clipped - 58 lines]
>  
> This posting is provided "AS IS" with no warranties, and confers no rights.
Linda Liu [MSFT] - 16 May 2007 03:54 GMT
Hi M,

Thank you for your prompt response.

The FindWindow function can only retrieves a handle to the top-level window
whose class name and window name match the specified strings. This function
does not search child windows.

To search child windows, use the FindWindowEx function. This function
searches the immediate child windows of the specified parent window.

The following is the code to retrieve the handle of the paneClassDC "Slide
Show" window.

using System.Runtime.InteropServices;

[DllImport("user32.dll")]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
static extern private IntPtr GetWindow(IntPtr hWnd, int uCmd);

const int GW_CHILD = 5;

IntPtr child1 = FindWindowEx(this.webBrowser1.Handle, IntPtr.Zero, "Shell
Embedding", "");
IntPtr child2 = FindWindowEx(child1, IntPtr.Zero, "Shell DocObject View",
"");
IntPtr child3 = FindWindowEx(child2, IntPtr.Zero, "childClass", "");
// because the 'childClass' window only has one child window and the child
window has a long window name, I use the GetWindow function to get the
child window for convenience
IntPtr child4 = GetWindow(child3, GW_CHILD);
IntPtr child5 = FindWindowEx(child4, IntPtr.Zero, "paneClassDC", "Slide
Show");

The variable child5 returns the handle of of the paneClassDC window.

Hope this helps.

Sincerely,
Linda Liu
Microsoft Online Community Support
lockness - 16 May 2007 10:52 GMT
LL

Sorry for the digression but FindWindowEx helps a great deal, now I get the
right handle. This gives me the option to construct a contol panel at the
bottom of the screen and run PP via interop, using SetForegroundWindow to
keep it on top.

But the original problem remains when using PP within the webbrowser.
(it's probably still there for the situation above, I haven't run a test on
the touchscreen yet ) I really dont want a mouse pointer appearing on the
screen.

But can this be avoided ?

Thanks again

M

> Hi M,
>
[quoted text clipped - 39 lines]
> Linda Liu
> Microsoft Online Community Support
Linda Liu [MSFT] - 18 May 2007 11:01 GMT
Hi M,

As for your original question to hide the cursor on WebBrowser, I am
consulting it in our inner discussion group.

As soon as I get an ansswer, I will get back to you.

BTW, do you really want this behaviour?

I appreciate your patience!

Sincerely,
Linda Liu
Microsoft Online Community Support
lockness - 20 May 2007 13:09 GMT
LL

The application will run on a kiosk with a touchscreen as the only user
interface.
There is no mouse or physical keyboard. The user will touch a button
or scrollbar to activate it.

In all the kiosk touchscreen apps I've seen there is no mouse pointer.

Thanks for your efforts so far

M

> Hi M,
>
[quoted text clipped - 10 lines]
> Linda Liu
> Microsoft Online Community Support
Linda Liu [MSFT] - 22 May 2007 11:54 GMT
Hi M,

After discussion, I get more information about displaying PowerPoint
document in WebBrowser control.

When we display a PowerPoint document in a WebBrowser on a form, a
PowerPoint process is created at background. You can see this process in
Task Manager.

However, cursor is specific to process, and this is why the cursor still
comes back on WebBrowser control when we hide the cursor for the WinForm
application and then move the pointer to the WebBrowser.

It is maybe impossible to hide the cursor on WebBrowser which is displaying
a PowerPoint document.

Sincerely,
Linda Liu
Microsoft Online Community Support
lockness - 24 May 2007 09:39 GMT
LL

I'm not sure how to react to that. I suppose I could view it as
good news and bad news. Its bad news that even Microsoft are
confounded by their products, but good news that my struggle with
controlling oher apps from .NET is justified.

So lets deal with what we've got. It sounds like I have to work with
the mouse pointer at a low level, as I had for key intercepts.

Presumably if I had low level control of the mounse pointer through
some API I could set its shape to anything ? including nothing at all ?

So my original question remains. How to hide the cursor. But am I
now asking it in the right forum ? Should I start looking for a
low level API group ?

Thanks

M.

> Hi M,
>
[quoted text clipped - 15 lines]
> Linda Liu
> Microsoft Online Community Support
Linda Liu [MSFT] - 28 May 2007 03:24 GMT
Hi M,

Thank you for your reply.

After doing more research, I found out a workaround for this issue, that is
to change the system cursor to a 'transparent' cursor when the application
is run and restore the previous system cursor when the application is
terminated. To set the system cursor, we could use the SetSystemCursor
Win32 function.

The following is a sample.

using System.Runtime.InteropServices;
public partial class Form1 : Form
   {
       [DllImport("user32.dll")]
       static extern bool SetSystemCursor(IntPtr hcur, int id);

       [DllImport("user32.dll")]
       static extern IntPtr LoadCursorFromFile(string lpFileName);
       
       [DllImport("user32.dll")]
       static extern IntPtr GetCursor();

        [DllImport("user32.dll")]
       static extern IntPtr CopyImage(IntPtr hImage,int uType,int
cxDesired,int cyDesired,int fuFlags);

        int OCR_NORMAL = 32512;
       int IMAGE_CURSOR = 2;
       int LR_COPYDELETEORG = 0x0008;

       void Form1_FormClosed(object sender, FormClosedEventArgs e)
       {
           // restore the system cursor
          SetSystemCursor(defaultCur, OCR_NORMAL);
       }

       private void Form1_Load(object sender, EventArgs e)
       {
           // get the handle of the current cursor
           defaultCur = GetCursor();
           // copy the default cursor to restore the system cursor when
the application exits
           defaultCur = CopyImage(defaultCur, IMAGE_CURSOR, 0, 0,
LR_COPYDELETEORG);
           // load a new transparent cursor
           IntPtr hcur = LoadCursorFromFile(Application.StartupPath +
@"\transparent.cur");          
           // set the system cursor to the new transparent cursor
           SetSystemCursor(hcur, OCR_NORMAL);          
       }
}

I searched the Internet and found a free cursor editor called RealWorld
Cursor Editor. You may use it to create a transparent cursor. You can
download it from the below link:

http://www.freedownloadscenter.com/Shell_and_Desktop/Cursor_Editing_Tools/Re
alWorld_Cursor_Editor.html

Hope this helps.

Sincerely,
Linda Liu
Microsoft Online Community Support
lockness - 28 May 2007 17:58 GMT
LL

I've just gone into Control Panel, Mouse, Pointers and set the mouse
to "NoCursor.cur". The mouser pointer then disappears.

I'll translate your code the VB and give that a go.

Strangley, while the test machine has the "noCursor.cur" option my
development machine does not. They both run XP-P !

I think this has finally solved the problem.
Thanks

> Hi M,
>
[quoted text clipped - 62 lines]
> Linda Liu
> Microsoft Online Community Support
Linda Liu [MSFT] - 29 May 2007 04:28 GMT
Hi M,

Thank you for your feedback.

The sample code I provided in my previous reply is to change the system
cursor programmatically. What's more, my sample code will restore the
previous cursor when the application is terminated.

I will translate the sample code in VB.NET for you.

Imports System.Runtime.InteropServices

Public Class Form1

   Private Declare Auto Function SetSystemCursor Lib "user32.dll" (ByVal
hcur As IntPtr, ByVal id As Integer) As Boolean
   Private Declare Auto Function LoadCursorFromFile Lib "user32.dll"
(ByVal lpFileName As String) As IntPtr
   Private Declare Auto Function GetCursor Lib "user32.dll" () As IntPtr
   Private Declare Auto Function CopyImage Lib "user32.dll" (ByVal hImage
As IntPtr, ByVal uType As Integer, ByVal cxDesired As Integer, ByVal
cyDesired As Integer, ByVal fuFlags As Integer) As IntPtr

   Const OCR_NORMAL As Integer = 32512
   Const IMAGE_CURSOR As Integer = 2
   Const LR_COPYDELETEORG As Integer = &H8

   Private defaultCur As IntPtr

   Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
       SetSystemCursor(defaultCur, OCR_NORMAL)
   End Sub

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
       defaultCur = GetCursor()
       defaultCur = CopyImage(defaultCur, IMAGE_CURSOR, 0, 0,
LR_COPYDELETEORG)
       Dim hcur As IntPtr = LoadCursorFromFile(Application.StartupPath +
"\transparent.cur")
       SetSystemCursor(hcur, OCR_NORMAL)
   End Sub

End Class

Hope this helps.

Sincerely,
Linda Liu
Microsoft Online Community Support
Linda Liu [MSFT] - 31 May 2007 10:45 GMT
Hi M,

How about the problem now?

If you still need our further assistance, please feel free to let me know.

Thank you for using our MSDN Managed Newsgroup Support Service!

Sincerely,
Linda Liu
Microsoft Online Community Support
lockness - 01 Jun 2007 15:13 GMT
LL

I suppose the original problem of hiding the cursor is solved.
What I'm doing now relates to finding the handles of child windows
you explained in an earlier reply.

The goal of the kiosk program is to present documents (pdf,ppt,etc) in a
manner that does not expose the document viewer's native controls,
but instead offers a simple Next/Previous control of its own.

I'm showing Powerpoint slides within a webbrowser as you know.
Hitting the PageDown/PageUp (or Space key) progresses the slideshow.
But remember this is a Kiosk without a keyboard. I've tried Sendkeys but found
it unreliable ( ever other sendkeys work for some unknown reason).

I've abandonded sendkeys and am experimenting with the API Sendmessage.

child1 = Win32.FindWindowEx(Me.WebBrowser1.Handle, IntPtr.Zero, "Shell
Embedding", "")
child2 = Win32.FindWindowEx(child1, IntPtr.Zero, "Shell DocObject View", "")
child3 = Win32.FindWindowEx(child2, IntPtr.Zero, "childClass", "")
 'because the 'childClass' window only has one child window and the child
 'window has a long window name, I use the GetWindow function to get the
 'child window for convenience
child4 = Win32.GetWindow(child3, GetWindow_Cmd.GW_CHILD)
child5 = Win32.FindWindowEx(child4, IntPtr.Zero, "paneClassDC", "Slide Show")

The above gets me the handle of the SlideShow.
I can then use sendmessage to simulate keystokes:

Win32.SendMessage(child5, WM_KEYDOWN, VK_NEXT, Nothing)
Win32.SendMessage(child5, WM_KEYUP, VK_NEXT, Nothing)

Using Spy++ to monitor SlideShow I can compare 'real' messages when
I hit the keyboard to my attempts with SendMessage.

My attempts are similar to the real messages but of course don't work.
Trouble is I can see VK_NEXT is in the real message but don't know
how to correctly format my own Sendmessage attempts.

If you could confirm what I'm doing is basically OK and point me
in the right direction for examples that would help.

Thanks and have a good weekend.

M.

> Hi M,
>
[quoted text clipped - 7 lines]
> Linda Liu
> Microsoft Online Community Support
lockness - 03 Jun 2007 12:17 GMT
LL

Using spy++ to carefully review messages I noticed they weren't
infact "sent" but "posted". So I switched from Sendmessage to Postmessage
and it now works. When I have time I'll looks in this whole area.

For now I want to achieve the same with a PDF loaded in the webbrowser.
With powerpoint the handle I wanted was 5 layers down, hence the use of
FindwindowEx 5 times. Acrobat appears to be 13 layers down ! But I
expect findwindowEx will get there in the end, unless there's a shortcut
to the right handle ?

M

> LL
>
[quoted text clipped - 54 lines]
> > Linda Liu
> > Microsoft Online Community Support
Linda Liu [MSFT] - 04 Jun 2007 10:50 GMT
Hi M,

Glad to hear that the problem of hiding cursor on the WebBrowser is solved
: )

As for finding a specific child window, I do more reading and find that the
Win32 function EnumChildWindows is more efficient. The EnumChildWindows
function enumerates the child windows that belong to the specified parent
window and pass each child window's handle to an application-defined
callback function. If a child window has its own child windows,
EnumChildWindows enumerates those windows as well. EnumChildWindows
continues until the last child window is enumerated or the callback
function return false.

In the application-defined callback function, we need to determine whether
the child window associated with the handle is the window we look for. To
do this, we could use Win32 function GetClassName to retrieve the name of
the class to which the specified window belongs and use Win32 function
GetWindowText to get text of the specified window's title bar.

The following is a sample. It requires that you add a WebBrowser and a
Button on the form.

Imports System.Runtime.InteropServices

Public Class Form1

   Declare Auto Function EnumChildWindows Lib "user32.dll" (ByVal
hWndParent As IntPtr, ByVal lpEnumFunc As MyDelegate, ByVal lParam As
WindowParam) As Boolean
   Declare Auto Function GetClassName Lib "user32.dll" (ByVal hWnd As
IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As
Integer) As Integer
   Declare Auto Function GetWindowText Lib "user32.dll" (ByVal hWnd As
IntPtr, ByVal lpString As System.Text.StringBuilder, ByVal nMaxCount As
Integer) As Integer

   Delegate Function MyDelegate(ByVal hwndChild As IntPtr, ByVal lParam As
WindowParam) As Boolean
   Private expectedChild As IntPtr

   Class WindowParam
       Private _className As String
       Private _windowName As String
       Public Property ClassName() As String
           Get
               Return _className
           End Get
           Set(ByVal value As String)
               _className = value
           End Set
       End Property
       Public Property WindowName() As String
           Get
               Return _windowName
           End Get
           Set(ByVal value As String)
               _windowName = value
           End Set
       End Property
       Public Sub New(ByVal cn As String, ByVal wn As String)
           _className = cn
           _windowName = wn
       End Sub
   End Class

   Private Function EnumChildProc(ByVal hwndChild As IntPtr, ByVal lParam
As WindowParam) As Boolean
       Dim className As New System.Text.StringBuilder(255)
       GetClassName(hwndChild, className, 255)

       Dim windowName As New System.Text.StringBuilder(255)
       GetWindowText(hwndChild, windowName, 255)

       If (className.ToString().Equals(lParam.ClassName) And
windowName.ToString().Equals(lParam.WindowName)) Then
           expectedChild = hwndChild
           Return False
       Else
           Return True
       End If
   End Function

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
       Me.WebBrowser1.Url = New Uri(Application.StartupPath + "\pdf1.pdf")
   End Sub

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
       Dim result As Boolean
       result = EnumChildWindows(Me.WebBrowser1.Handle, New
MyDelegate(AddressOf EnumChildProc), New WindowParam("AVL_AVView",
"AVPageView"))
       If (result = False) Then
           MessageBox.Show(Convert.ToString(expectedChild.ToInt32(), 16))
       End If
   End Sub
End Class

Hope this helps.
If you have anything unclear, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support
Linda Liu [MSFT] - 06 Jun 2007 11:57 GMT
Hi M,

How about the problem now?

If you have anything unclear, please feel free to let me know.

Thank you for using our MSND Managed Newsgroup Support Service!

Sincerely,
Linda Liu
Microsoft Online Community Support
lockness - 08 Jun 2007 10:01 GMT
LL

The original problem hiding the cursor has a workable solution (change
the cursor to "blank") and the other problem communicating with powerpoint
and acrobat have a solution with findwindowex ( although EnumChildWindows
may be a better solution)

Right now there are other issues I'm working through, but they're just plain
design and coding issues. But there is another outstanding technical issue:

"Silent printing" or printing without a print dialog popping up.
Powerpoint within the browser window is OK, the print request to
the browser generates "printing page 1,2,3,etc" thats OK.
But AcrobatReader comes up with a print dialog box.

One solution would be to pay Adobe for their full product that exposes
lots of useful methods, but of course we want to minimize the expense
of out product.

I've tried using acrobat activex directly (no browser window) that was
partly successful, but unreliable.

I suspect I may end up be using EnumChildWindows to intercept the dialog and
press the OK key.

When this problem becomes a priority should I start a new thread or carry on
here ???

Thanks

M

> Hi M,
>
[quoted text clipped - 7 lines]
> Linda Liu
> Microsoft Online Community Support
Linda Liu [MSFT] - 11 Jun 2007 12:56 GMT
Hi M,

Firstly, you'd better post a new thread for your new question for next time
: )

As for the question of sliently printing a PDF file, I searched the
Internet and found two solutions.

One solution is to use the Win32 API function ShellExecute to perform the
'print' verb on a PDF file. If you right click a PDF file in Windows
Explorer, and choose 'print' command, you should see that the PDF file is
printed sliently.

For more information on the ShellExecute function, you may refer to the
following document:

'ShellExecute Function'
http://msdn2.microsoft.com/en-us/library/ms647732.aspx

Another solution is to use /t command line to print a PDF file silently.
You can then launch the command line using the Process class in your
application. For more information on the /t command line, you may read the
followng article:

'How To: Reader command line printing'
http://support.adobe.com/devsup/devsup.nsf/docs/52080.htm

Hope this helps.

Sincerely,
Linda Liu
Microsoft Online Community Support
Linda Liu [MSFT] - 13 Jun 2007 13:14 GMT
Hi M,

How about the problem now?

If you need our further assistance, please feel free to let know know.

Thank you for using our MSDN Managed Newsgroup Support Service!

Sincerely,
Linda Liu
Microsoft Online Community Support
lockness - 14 Jun 2007 09:44 GMT
Hi LL

With regard to silent printing your suggestions did get rid of
the print dialog but in all cases the acrobat reader program
muscles its way to the top of the desktop. Setting topmost=true
on my app helps, but then the taskbar flashes up. Its a kludge
but finally I used ShowWindow(hndl,HIDE) to make the takbar
invisible.

The next step is to check the printer is actually available for print
before printing, and issue some message when printing complete.
I know that .NET does not directly support the print spooler
system and my previous attempts to get the printer status with WMI
always returned a positive state even when the printer was turned
off, so there could be a new question coming up soon ;-)

Thanks
M

> Hi M,
>
[quoted text clipped - 7 lines]
> Linda Liu
> Microsoft Online Community Support

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.