[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Windows API



PureBytes Links

Trading Reference Links

<x-html><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content="text/html; charset=iso-8859-1" http-equiv=Content-Type>
<META content="MSHTML 5.00.2614.3401" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT size=2>A re-post (previous did not make it to&nbsp;the 
List).</FONT></DIV>
<DIV><BR>Regards,<BR>Ton Maas<BR><A 
href="mailto:ms-irb@xxxxxxxxxxxxxxxx";>ms-irb@xxxxxxxxxxxxxxxx</A><BR>Dismiss the 
".nospam" bit (including the dot) when replying and<BR>note the new address 
change. Also for my Homepage<BR><A 
href="http://home.planet.nl/~anthmaas";>http://home.planet.nl/~anthmaas</A></DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<BLOCKQUOTE 
style="BORDER-LEFT: #000000 2px solid; MARGIN-LEFT: 5px; MARGIN-RIGHT: 0px; PADDING-LEFT: 5px; PADDING-RIGHT: 0px">
  <DIV style="FONT: 10pt arial">----- Original Message ----- </DIV>
  <DIV 
  style="BACKGROUND: #e4e4e4; FONT: 10pt arial; font-color: black"><B>From:</B>&nbsp;A.J. 
  Maas </DIV>
  <DIV style="FONT: 10pt arial"><B>To:</B> <A 
  href="mailto:metastock@xxxxxxxxxxxxx"; 
  title=metastock@xxxxxxxxxxxxx>metastock@xxxxxxxxxxxxx</A> </DIV>
  <DIV style="FONT: 10pt arial"><B>Sent:</B> zaterdag 11 september 1999 
  19:11</DIV>
  <DIV style="FONT: 10pt arial"><B>Subject:</B> Re: Windows API</DIV>
  <DIV><BR></DIV>
  <DIV><FONT size=2>Windows API : This below can be found @ </FONT></DIV>
  <DIV><FONT size=2><A 
  href="http://msdn.microsoft.com/library/periodic/period96/D1/FT0296.htm";>http://msdn.microsoft.com/library/periodic/period96/D1/FT0296.htm</A></FONT></DIV>
  <DIV>&nbsp;</DIV>
  <DIV><FONT size=2>Also click the "show toc"-icon below to go to the MSDN 
  Library (eg a&nbsp;treasure for Windows developers</FONT></DIV>
  <DIV><FONT size=2>and not to be mixed up with the Windows library files (eg 
  drivers + dll's + ocx's etc.).</FONT></DIV>
  <DIV><FONT size=2>&nbsp;</DIV></FONT>
  <DIV><FONT size=2>And&nbsp;naturaly there is more:</FONT></DIV>
  <DIV><FONT size=2><A 
  href="http://search.microsoft.com/us/results.asp?SName=Developer+Sites&amp;SPath=http://msdn.microsoft.com&amp;SCatalog=Developer&amp;IntCat=11&amp;Boolean=PHRASE&amp;Nq=TRUE&amp;qu=WIN32API&amp;submit1=search";>http://search.microsoft.com/us/results.asp?SName=Developer+Sites&amp;SPath=http://msdn.microsoft.com&amp;SCatalog=Developer&amp;IntCat=11&amp;Boolean=PHRASE&amp;Nq=TRUE&amp;qu=WIN32API&amp;submit1=search</A></FONT></DIV>
  <DIV><FONT size=2>(note: the lines above were&nbsp;split but should be 
  copied+pasted in full as&nbsp;it is also one(1)&nbsp;full website's 
  address)</FONT></DIV>
  <DIV>&nbsp;</DIV>
  <DIV><FONT size=2>Regards,<BR>Ton Maas<BR><A 
  href="mailto:ms-irb@xxxxxxxxxxxxxxxx";>ms-irb@xxxxxxxxxxxxxxxx</A><BR>Dismiss 
  the ".nospam" bit (including the dot) when replying and<BR>note the new 
  address change. Also for my Homepage<BR><A 
  href="http://home.planet.nl/~anthmaas";>http://home.planet.nl/~anthmaas</A></FONT></DIV>
  <DIV>&nbsp;</DIV>
  <DIV>&nbsp;</DIV>
  <DIV><FONT size=2>----- Original Message ----- </FONT>
  <DIV><FONT size=2>From: Walter Lake</FONT></DIV>
  <DIV><FONT size=2>To: Metastock bulletin board &lt;<A 
  href="mailto:metastock@xxxxxxxxxxxxx";>metastock@xxxxxxxxxxxxx</A>&gt;</FONT></DIV>
  <DIV><FONT size=2>Sent: donderdag 9 september 1999 15:34</FONT></DIV>
  <DIV><FONT size=2>Subject: Windows API</FONT></DIV></DIV>
  <DIV><BR></DIV>
  <DIV><FONT size=2>&gt; Thanks for your email. Sorry but I don't know how to do 
  that.<BR>&gt; <BR>&gt; There is a whole section of advanced Excel VBA 
  programming using Windows API<BR>&gt; (Application Programming Interface) that 
  is covered in the WROX programmers<BR>&gt; reference book. Usually, that kind 
  of access to the Windows platform and<BR>&gt; ".dll's" is used by C and C+ 
  programmers.<BR>&gt; <BR>&gt; Where Windows API programming is of interest is 
  when you want to take over<BR>&gt; the entire Excel interface and create your 
  own icon's etc.<BR>&gt; <BR>&gt; As I mentioned earlier, you can make Excel 
  look less and less like Excel and<BR>&gt; more like your own program using VBA 
  and VBA access to Windows API.<BR>&gt; <BR>&gt; Using Windows API, as far as I 
  know, is not only complicated but "risky"<BR>&gt; because of the lack of error 
  messages and difficulty figuring out what went<BR>&gt; wrong when things don't 
  work correctly.<BR>&gt; <BR>&gt; Personally, I'm going to leave all of that to 
  the C and C+ programmers.<BR>&gt; "Plain" VBA is complicated enough for an 
  untrained and "clueless" programmer<BR>&gt; such as myself.<BR>&gt; <BR>&gt; 
  Maybe Guy or Ton can post some general info about Windows API and the 
  MSDN<BR>&gt; library files.<BR>&gt; <BR>&gt; There's suppose to be a 
  "win32api.txt" file that has all of the declarations<BR>&gt; for the core 
  windows functions written in VBA notation. I don't know where<BR>&gt; it is or 
  how to find it. Maybe Guy uses it in his programming.<BR>&gt; <BR>&gt; Best 
  regards<BR>&gt; <BR>&gt; Walter<BR>&gt;&nbsp;<BR><!--TOOLBAR_START--><!--TOOLBAR_EXEMPT--><!--TOOLBAR_END--><!--SYNC_START-->
  <SCRIPT language=JavaScript src="/library/synch.js"></SCRIPT>
  </FONT></DIV>
  <DIV><FONT size=2>&nbsp;<A 
  href="http://msdn.microsoft.com/isapi/msdnlib.idc?theURL=/library/periodic/period96/d1/ft0296.htm"; 
  target=_top><IMG border=0 height=17 
  src="mhtml:mid://00000220/!http://msdn.microsoft.com/library/images/msdn/art/mlibfram.gif"; 
  width=75></A> <!--SYNC_END--></DIV>
  <P><FONT face="Verdana, Arial, Helvetica" size=2>
  <H1>Use the Windows API to Print to Multiple Print Queues</H1>
  <P>Richard Aman</P>
  <P><I>Richard Aman is director of software engineering at Loren Industries, a 
  jewelry manufacturing company with headquarters in Hollywood, Florida. Richard 
  has been developing business solutions in FoxBASE/FoxPro since 1988 and 
  regularly gives presentations at his local Fox User Group. CompuServe 
  73700,141.</I></P>
  <P>This article originally appeared in the February 1996 issue of FoxTalk, 
  published by Pinnacle Publishing Inc., PO Box 888, Kent, WA 98035-0888; 
  800-788-1900; 206-251-1900; http://www.pinpub.com.</P>
  <P>Windows provides a wealth of services for controlling network connections. 
  Richard Aman shows how to use these services in either FoxPro 2.x or Visual 
  FoxPro to easily send a report to any available output device. In the process, 
  you'll learn about Visual FoxPro's new variant of DECLARE, which allows you to 
  call external DLL routines as if they were native UDFs. You'll also learn how 
  to use several useful Windows API routines.</P>
  <P>ONE of the more difficult application types I've implemented is an 
  automatic scheduler. A scheduler performs procedures at various scheduled and 
  unscheduled times throughout the day. The procedures must perform in 
  unattended mode and make decisions without user input. Along with 
  software-related decisions like branching and looping, the procedures must 
  make hardware decisions. For example, the software must decide which printer 
  to send output to, which network connection to use, when to reset the 
  software, and which users are logged on when.</P>
  <P>When I implemented the scheduler in Windows, the main design decision was 
  how to allow the system to use different printers in different locations for 
  the various output reports&#8212;key in an order-entry and work progress-based 
  system like this one. I designed the system to make decisions based on orders 
  entered, and by the various stages of manufacture that pieces have 
  achieved.</P>
  <H2>The Win.INI route</H2>
  <P>To choose an output printer, I initially used sample code from the 
  Microsoft Developer's Network (MSDN) CD. That sample code had multiple 
  printers installed in Windows, then modified the WIN.INI file to change the 
  default printer. The method worked fine, although it had limitations. First, 
  it required that all printers to be used be installed in Windows&#8212;a problem if 
  you want to use the application on different machines. The second limitation 
  was that Windows has only a limited number of printer ports. Though it's 
  possible to have several printers assigned to the same port, keeping track of 
  them can get messy. The third limitation is that it takes time to modify 
  WIN.INI and notify running applications to update themselves with the 
  changes.</P>
  <P>The method detailed on the MSDN CD used the Windows API functions 
  GetProfileString() and PutProfileString() to access WIN.INI. This made me 
  wonder what other functions for switching printers might be buried in the 
  Windows API. I started looking through the Microsoft Developer's Network CD 
  and the TechNet CD (both excellent resources) and the Windows API help file 
  that comes with Visual FoxPro Professional Edition for other approaches to 
  this problem.</P>
  <H2>A better way</H2>
  <P>That's when I came across the WNetGetConnection(), WNetAddConnection(), and 
  WNetCancelConnection() functions. These three Windows API functions combine to 
  give you almost unlimited programmatic control over the network connections 
  through an application. WNetGetConnection() returns the name of the network 
  connection that a local device is mapped to, or NULL if the device isn't 
  mapped on the network. WNetAddConnection() maps a local device to a network 
  connection if it's not already connected. And WNetCancelConnection() 
  disconnects a local device from a network connection. With these three 
  functions, I implemented multiple printer output through LPT1 alone. I also 
  found two other useful Windows API functions: WNetGetUser(), which returns the 
  user network login ID, and ExitWindows(), which can be used to restart Windows 
  from within FoxPro.</P>
  <P>My automatic scheduler application scans the orders table at a recurring 
  interval for any new orders. When new orders are found, they're copied to 
  separate temporary tables for printing. Based on the type, orders can print at 
  one of three places in the plant. The print routine is passed through three 
  parameters, which tell the routine the name of the temporary table, the report 
  form to use, and where to send output. When the routine processes the print 
  location decision, it calls WNetGetConnection() to check whether LPT1 is 
  connected to a network print queue. If a current connection exists, it calls 
  WNetCancelConnection() to disconnect LPT1 from the current network print 
  queue. It then calls WNetAddConnection() to connect LPT1 to the proper network 
  print queue. (To prevent a connection error, you'll need to cancel the 
  existing connection before creating a new connection..)</P>
  <H2>The basics</H2>
  <P>Before I get to my sample code, I want to quickly cover some basic 
  requirements for using this method of printer control and for using any of the 
  Windows API functions (or functions in any Windows DLL).</P>
  <P>If you're using FoxPro 2.6 for Windows, first load in the library file 
  FoxTools.fll, (supplied with FoxPro 2.6). This library file loads with the 
  command SET LIBRARY TO FoxTools. Once the library is loaded, your program has 
  access to a pair of functions called RegFn() and CallFn(). RegFn() is used to 
  register Windows API functions to FoxPro. CallFn() is used to call the 
  functions previously registered with RegFn(). In Visual FoxPro 3.0, the 
  DECLARE command replaces the need for FoxTools.fll and the RegFn() and 
  CallFn() routines . This new DECLARE command is also used to register Windows 
  API functions. Once the functions have been registered, they're called just 
  like the internal FoxPro functions. However, for backward compatibility, 
  FoxTools.fll, RegFn() and CallFn() can still be used in FoxPro 3.0. (Refer to 
  the Visual FoxPro 3.0 help file for more information on the DECLARE 
  command.)</P>
  <P>If you're working in FoxPro 2.x and are new to FoxTools/RegFn/CallFn, you 
  can get details from "Use Microsoft Windows Services from FoxPro" by Robert W. 
  Lord (<I>FoxTalk</I>, March 1994). Back issues can be ordered at 800-788-1900. 
  In the meantime, here's a brief rundown of these commands and the new Visual 
  FoxPro replacements for them:</P>
  <H3>Loading the FoxTools.fll library</H3>
  <P>First, load the FoxTools.fll library for FoxPro 2.6:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> SET LIBRARY TO SYS(2004) + 'FoxTools.fll' ADDITIVE</FONT></CODE></PRE>
  <P>This command line uses the FoxPro function SYS(2004) to get FoxPro's home 
  directory, which is where FoxTools.fll is installed during normal 
  installation. Also, use the ADDITIVE clause to add the library to any existing 
  loaded libraries; otherwise, FoxTools.fll will replace any existing loaded 
  libraries.</P>
  <H3>Using RegFn()</H3>
  <P>The FoxTools function RegFn() registers a Windows API function with FoxPro. 
  RegFn() takes three required parameters and one optional parameter. The first 
  parameter is the name of the Windows API function you want to register. The 
  second parameter is a string containing letter designations for the types of 
  parameters the Windows API function requires ( 'C' for character or string, 
  'I' for integer, and so forth). The third parameter is a letter designation 
  for the type of value the Windows API function will return to FoxPro. The 
  fourth and optional parameter is the name of the Windows DLL that contains the 
  function you want to register. If you don't include the DLL name, FoxPro 
  automatically looks in the standard Windows libraries (USER.EXE, KRNL386.EXE, 
  and GDI.EXE in Windows 3.x) to try to find the Windows API function. If the 
  function isn't found, an error code is returned. If the function is 
  successfully registered, a function handle is returned. That handle is then 
  used by CallFn() to access the Windows API function, as I describe later.</P>
  <H3>Using CallFn()</H3>
  <P>The FoxTools function CallFn() is used to access a Windows API function 
  from within FoxPro once it has been registered with RegFn(). The parameters 
  passed to CallFn() are the Windows API function handle returned by RegFn(), 
  and the parameters specified in the second parameter in RegFn() when the 
  Windows API function was registered. </P>
  <H3>Using DECLARE in Visual FoxPro</H3>
  <P>DECLARE is an enhanced command in Visual FoxPro 3.0. In addition to 
  defining arrays, the DECLARE command also removes the need for using FoxTools 
  to access the Windows API functions. DECLARE allows the application to 
  directly register Windows API functions with FoxPro. Once the functions are 
  registered, they can be called like any other FoxPro internal function. The 
  first parameter to the DECLARE command is the Windows API function return 
  type. The second parameter is the name of the function you're registering. The 
  third parameter is the DLL containing the Windows API function. The remainder 
  of the parameters are the parameter types that FoxPro will pass to the Windows 
  API function.</P>
  <H2>The Windows API functions</H2>
  <H3>WNetGetConnection()</H3>
  <P>WNetGetConnection() is used to retrieve the network connection to which a 
  local device is mapped. The first parameter is a variable containing the name 
  of the local device you want to check. The second parameter is a variable 
  initialized to spaces ( I use 255 ) and will be supplied with the connection 
  name by WNetGetConnection(). The last parameter is a variable containing the 
  length of the second parameter ( in this case 255 ). All three parameters need 
  to be passed by reference. After initializing the variables, register the 
  function with FoxPro. This lets FoxPro know that the function will be passed 
  three parameters by reference, two strings and one integer, and the function 
  will return an integer. Ensure the second parameter buffer is empty before 
  calling this function, because an error won't clear the buffer and you might 
  get incorrect results.</P>
  <P>Here's the syntax for setting up the WNetGetConnection call, first for 
  FoxPro 2.x, then for Visual FoxPro:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.x
lnGetConn = RegFn('WNetGetConnection','@C@x@I','I')
* Visual FoxPro
DECLARE INTEGER WNetGetConnection IN win32api ;
       STRING @, STRING @, INTEGER @</FONT></CODE></PRE>
  <P>Call the function to return the current connection for the specified 
  device:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.x
lnRetVal = CallFn(lnGetConn, @lcDeviceName, ;
         @lcConnName, @lnBuffLen)
* Visual FoxPro
lnRetVal = WNetGetConnection(@lcDeviceName, ;
               @lcConnName, @lnBuffLen)</FONT></CODE></PRE>
  <P>After the call to WNetGetConnection(), the buffer lcConnName will either 
  contain the name of the network connection for the specified local device or 
  will be empty if no connection currently exists for the local device. It will 
  also be empty if an error occurred. Also, be sure to check the return value 
  for any error codes. The Windows API return codes for WNetGetConnection() 
  follow, as found in the Windows SDK:</P>
  <P>0 The function was successful.</P>
  <P>8 The system was out of memory.</P>
  <P>50 The function was not supported.</P>
  <P>59 An error occurred on the network.</P>
  <P>87 The local device name parameter was not a valid local device.</P>
  <P>234 The buffer was too small. ( The connection name is longer than </P>
  <P>the allotted buffer length. )</P>
  <P>487 The pointer was invalid.</P>
  <P>2250 The local device name parameter was not a redirected local </P>
  <P>device.</P>
  <H3>WNetAddConnection()</H3>
  <P>WNetAddConnection() is used to map a local device to a network connection. 
  The first parameter is the network connection to map the device to. The second 
  parameter is the password to use and should be a null string to use the 
  default password. Finally, the third parameter is the local device to map. 
  After initializing the variables, register the function with FoxPro. This lets 
  FoxPro know that the function will be passed three parameters as strings, and 
  will return one integer:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.6
lnAddConn = RegFn('WNetAddConnection','CCC','I')

* Visual FoxPro
DECLARE INTEGER WNetAddConnection IN win32api ;
    STRING, STRING, STRING</FONT></CODE></PRE>
  <P>Call the function to map the local device to the network connection:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.x
lnRetVal = CallFn(lnAddConn,'\\SERVER1\HP4','','LPT1:')

* Visual FoxPro
lnRetVal = WNetAddConnection('\\SERVER1\HP4','','LPT1:')</FONT></CODE></PRE>
  <P>This function returns 0 if successful, or an error number for any error 
  that occurs while attempting to create the network connection. I've listed the 
  Windows API return codes for WNetAddConnection(), which follow, as found in 
  the Windows SDK.</P>
  <TABLE border=0 cols=2>
    <COLGROUP>
    <COL vAlign=top width=68>
    <COL vAlign=top width=226></COLGROUP>
    <TBODY>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>0</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The 
        function was successful.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>5</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>A security 
        violation occurred.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>8</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The system 
        was out of memory.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>50</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The 
        function was not supported.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>59</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>An error 
        occurred on the network.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>67</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The network 
        resource name was invalid.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>85</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The local 
        device was already connected to a remote resource.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>86</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The 
        password was invalid.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
      size=2>487</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The pointer 
        was invalid.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
      size=2>1200</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The local 
        device name was invalid.</FONT></TD></TR></TBODY></TABLE>
  <P><BR></P>
  <H3>WNetCancelConnection()</H3>
  <P>WNetCancelConnection() is used to remove a network connection mapping from 
  a local device. This is necessary because the WNetAddConnection() function 
  will return an error if the device that you are trying to map is already 
  mapped to a network connection. For this reason, I recommend checking the 
  network mapping for the local device before attempting to create a new 
  connection. Also, I recommend releasing any network mapping that exists first. 
  The first parameter is the local device to cancel the network connection to. 
  The second parameter tells Windows whether to close any open files, or simply 
  to return an error. The second parameter should be 0 to close open files 
  before disconnecting. After initializing the variables, register the function 
  with FoxPro. This lets FoxPro know that the function will be passed two 
  parameters, one string and one integer, and will return one integer.</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.6
lnCancelConn = RegFn('WNetCancelConnection','CI','I')

* Visual FoxPro
DECLARE INTEGER WNetCancelConnection IN win32api ;
    STRING, INTEGER</FONT></CODE></PRE>
  <P>Call the function to cancel the connection for the specified local 
  device:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.6
lnRetVal = CallFn(lnCancelConn,'LPT1:',0)

* Visual FoxPro
lnRetVal = WNetCancelConnection('LPT1:',0)</FONT></CODE></PRE>
  <P>This function returns 0 if successful, or it returns an error number for 
  any error that occurs while attempting to cancel the network connection. 
  Following are the Windows API return codes for WNetCancelConnection(), as 
  found in the Windows SDK:</P>
  <TABLE border=0 cols=2>
    <COLGROUP>
    <COL vAlign=top width=72>
    <COL vAlign=top width=243></COLGROUP>
    <TBODY>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>0</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The 
        function was successful.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>8</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The system 
        was out of memory.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>50</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The 
        function was not supported.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>59</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>An error 
        occurred on the network.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>87</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The local 
        device name parameter was not a valid local device </FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
        size=2>&nbsp;</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>or network 
        name. </FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
      size=2>487</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The pointer 
        was invalid.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
      size=2>2250</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The local 
        device name parameter was not a redirected local </FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
        size=2>&nbsp;</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>device or 
        currently accessed network resource.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
      size=2>2401</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>Files were 
        open and the fForce parameter was 0. </FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
        size=2>&nbsp;</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The 
        connection was not canceled.</FONT></TD></TR></TBODY></TABLE>
  <P><BR></P>
  <H3>WNetGetUser()</H3>
  <P>WNetGetUser() is used to return the network login ID of the machine the 
  application is running on. The first parameter is a variable containing the 
  local name to return the network login ID for. It should be NULL for the 
  current machine. The second parameter is a variable initialized to spaces (I 
  use 255 spaces) and will be filled in by WNetGetUser() with the network login 
  ID. The third parameter is the length of the second parameter. All three 
  parameters need to be passed in by reference in order for the function to 
  operate correctly. After initializing the variables, register the function 
  with FoxPro. This lets FoxPro know that the function will be passed two 
  parameters by reference, one string and one integer, and the function will 
  return one integer. Use NULL for the first parameter to get the current 
  sign-on name because if the user is signed on more than once, the system makes 
  a random choice of which login name to return:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.x
lnGetUser = RegFn('WNetGetUser','@C@x@I','I')

* Visual FoxPro
DECLARE INTEGER WNetGetUser IN win32api ;
    STRING @, STRING @, INTEGER @</FONT></CODE></PRE>
  <P>Call the function to get the network login ID of the machine:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.x
lnRetVal = CallFn(lnGetUser,@lcUserID,@lnBuffLen)
lnRetVal = WNetGetUser(@lcUserID,@lnBuffLen)</FONT></CODE></PRE>
  <P>After the call to WNetGetUser(), the buffer lcUserID will contain either 
  the network login ID or will be empty if the machine isn't logged in to the 
  network. Also, check the return value for any error codes. Following are the 
  Windows API return codes for WNetGetUser(), as found in the Windows SDK:</P>
  <TABLE border=0 cols=2>
    <COLGROUP>
    <COL vAlign=top width=59>
    <COL vAlign=top width=297></COLGROUP>
    <TBODY>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>8</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The 
        function could not allocate sufficient memory to </FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
        size=2>&nbsp;</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>complete 
        its operation.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>50</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>This 
        function is not supported. </FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
size=2>59</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>A network 
        error occurred.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
      size=2>234</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The buffer 
        was too small to hold the complete user name. </FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
      size=2>487</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The pointer 
        is invalid.</FONT></TD></TR>
    <TR>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" 
      size=2>2202</FONT></TD>
      <TD vAlign=top><FONT face="Verdana, Arial, Helvetica" size=2>The user is 
        not logged in; there is no current user name. 
</FONT></TD></TR></TBODY></TABLE>
  <P><BR></P>
  <H3>ExitWindows() and ExitWindowsEx()</H3>
  <P>ExitWindows() has two uses of interest, based on the first parameter passed 
  in. The first parameter is a flag to tell Windows to either reboot or exit. 
  The second parameter is reserved and should be 0. If you pass in a 67 to the 
  first parameter, Windows will close down any running applications and exit to 
  the DOS prompt. If you pass in a 66, Windows will close down any running 
  applications and restart Windows. (the function is called ExitWindowsEx() in 
  32-bit Windows; the first parameter should be 0 to restart Windows.) I use a 
  66 in the automatic scheduler application . After initializing the variables, 
  register the function with FoxPro. This lets FoxPro know that the function 
  will be passed two parameters, both integers, and the function will return one 
  integer:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.x
lnExitWin = RegFn('ExitWindows','II','I')

* Visual FoxPro
DECLARE INTEGER ExitWindowsEx IN user32 ;
    INTEGER, INTEGER</FONT></CODE></PRE>
  <P>Call the function to restart Windows:</P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> * FoxPro 2.x
lnRetVal = CallFn(lnExitWin,66,0)

* Visual FoxPro
lnRetVal = ExitWindowsEx(0,0)</FONT></CODE></PRE>
  <P>ExitWindows() and ExitWindowsEx() have only two return codes: 0 or FALSE if 
  an error occurred, and 1 or TRUE if the function call was successful. In this 
  use of ExitWindows() or ExitWindowsEx(), you probably need only check for a 
  failure return code, since a successful call would have restarted Windows and 
  FoxPro, meaning the return code value would have been released. But a check 
  for success might be important in other uses.</P>
  <P>Why use ExitWindows() or ExitWindowsEx()? I use ExitWindows() because of a 
  "memory leak" in FoxPro for Windows 2.6, which my scheduler runs under. When 
  FoxPro generates a report, some of the memory used isn't released back to the 
  pool of free memory. Consequently, after a certain number of reports, FoxPro 
  can run out of memory. In my case, problems occur after approximately 75 work 
  production tickets, each with a bitmap of the item and several different 
  fonts. To prevent this, I set up FoxPro in the Windows StartUp group with a 
  command line call to the automatic scheduler. Then, every 15 minutes I call a 
  procedure called ResetWin (included on this month's Companion Disk), which 
  closes down FoxPro and restarts Windows. When Windows starts up, it runs 
  FoxPro from the StartUp group, which then restarts the automatic scheduler, 
  which picks up where it left off&#8212;but with refreshed memory. Everything runs 
  smoothly with this scheme in place.</P>
  <P>Presumably, this memory leak has been fixed in Visual FoxPro, but you may 
  still want to use ExitWindowsEx() to automatically shut down or restart some 
  application types, perhaps at particular times of the day when demand is 
  minimal. It often helps to get a "clean slate" periodically for an automated 
  server application on a dedicated workstation, particularly if the application 
  has the potential of running unattended for days or weeks.</P>
  <P>Listing 1 illustrates my basic method of printer control. Prior to this 
  procedure, the application will have selected the records to be printed, the 
  report form to use, and the network print queue destination, all of which are 
  passed in through parameters. I first initialize my variables and save the 
  current library setting. I then make sure the Foxtools library is loaded for 
  version 2.x. Next, I register the Windows API functions with FoxPro ( using 
  the DECLARE command for version 3.0 or the RegFn() for version 2.x ). Then I 
  check for and release any existing connection for LPT1: using 
  WNetGetConnection(). I then set LPT1: to the desired network print queue with 
  WNetAddConnection(). After all is set up properly, I loop through the source 
  table and generate a full-page form for each record (this allows other users 
  to insert print jobs between my frequent multi-page output). Finally, I make a 
  call to GetNetID() to see if I'm on the automatic scheduler. If so, I reset 
  LPT1: to a default network print queue. I then restore the previous library 
  setting and exit the routine.</P>
  <P>The call to the GetNetID UDF deserves a little more explanation. GetNetID() 
  is included on this month's Companion Disk. It calls the Windows WNetGetUser() 
  function to return the network login ID of the machine the application is 
  running on. This can be used for a variety of things. In AutoPrnt, I check the 
  network ID with GetNetID() to see if the application print routine is running 
  on the automatic scheduler machine. If so, I re-map the printer back to the 
  default queue so normal output that doesn't need to be specifically redirected 
  can be printed on the central printer. </P>
  <P><B>Listing 1. The AutoPrnt procedure.</B></P>
  <P><BR></P><PRE><CODE><FONT face="Verdana, Arial, Helvetica" size=2> ********************************************************
* PROCEDURE AutoPrnt
********************************************************
* Author............: Richard L. Aman
*) Description.......: A scaled down version of the print
*)          : engine for the automatic scheduler
* Calling Samples...: DO AutoPrnt WITH cSrcTable,
*)          : cFormName, cPrinter
* Parameter List....: cSrcTable - table containing
*)          : records to print
*          : cFormName - name of form to use
*          : cPrinter - report destination

PROCEDURE AutoPrnt
PARAMETERS cSrcTable, cFormName, cPrinter

*-- define variables
PRIVATE lcFormName, lcPrinter, lcReport, lcOldPrinter, ;
    lcOldLibrary, lnAddConn, lnDelConn, lnGetConn, ;
    lcDeviceName, lcConnName, lnBuffLen, ;
    llVersion3, lcConnTo, lnRetVal
*-- init variables
lcFormName = cFormName
lcPrinter = cPrinter
lcReport = lcFormName
lcOldPrinter = ''
lcOldLibrary = SET('LIBRARY')
lcDeviceName = 'LPT1'
lcConnName = SPACE(254)
lnBuffLen = LEN(lcConnName)
llVersion3 = '3.0' $ VERSION()
lcConnTo = ''
lnRetVal = 0
*--ensure that foxtools library is loaded
IF NOT llVersion3

 IF NOT 'FOXTOOLS' $ UPPER( lcOldLibrary )
  SET LIBRARY TO SYS( 2004 ) + 'FOXTOOLS.FLL' ADDITIVE
 ENDIF

ENDIF
*-- register the Windows API functions
IF llVersion3
 DECLARE INTEGER WNetAddConnection IN win32API ;
     STRING, STRING, STRING
 DECLARE INTEGER WNetCancelConnection IN win32API ;
     STRING, INTEGER
 DECLARE INTEGER WNetGetConnection IN win32API ;
     STRING @, STRING @, INTEGER @
ELSE
 lnAddConn = RegFn('WNetAddConnection','CCC','I')
 lnDelConn = RegFn('WNetCancelConnection','CI','I')
 lnGetConn = RegFn('WNetGetConnection','@C@x@I','I')
ENDIF
*-- check for an existing connection
IF llVersion3
 lnRetVal = WNetGetConnection(@lcDeviceName, ;
                @lcConnName,@lnBuffLen)
ELSE
 lnRetVal = CallFn(lnGetConn,@lcDeviceName, ;
          @lcConnName,@lnBuffLen )
ENDIF

IF NOT EMPTY( lcConnName )

 IF llVersion3
  lnRetVal = WinNetCancelConnection('LPT1:',0)
 ELSE
  lnRetVal = CallFn(lnDelConn,'LPT1:',0)
 ENDIF

ENDIF

*-- set the printer to the correct queue
DO CASE

 CASE lcPrinter = 'MIS'
  lcConnTo = '\\SERVER1\MIS'
        
 CASE lcPrinter = 'QC'
  lcConnTo = '\\SERVER1\HP4'
        
 CASE lcPrinter = 'PRODUCTION'
  lcConnTo = '\\SERVER2\PRODPRINT'
        
ENDCASE

IF llVersion3
 lnRetVal = WNetAddConnection( lcConnTo, '','LPT1:')
ELSE
 lnRetVal = CallFn(lnAddConn,lcConnTo,'','LPT1:')
ENDIF

*-- print the report for each record
GO TOP

SCAN WHILE LASTKEY() &lt;&gt; 27 &amp;&amp; allow ESC
 REPORT FORM &amp;lcReport TO PRINTER NEXT 1 NOCONSOLE
ENDSCAN

*-- clean up and return
IF GetNetID() = 'SCHEDULE'

 IF llVersion3
  lnRetVal = WNetCancelConnection('LPT1:',0)
  lnRetVal = WNetAddConnection('\\SERVER1\PRINTQ_0',;
                 '','LPT1:')
    ELSE
  lnRetVal = CallFn(lnDelConn,'LPT1:',0)
  lnRetVal = CallFn(lnAddConn,'\\SERVER1\PRINTQ_0',;
           '','LPT1:')
 ENDIF

ENDIF

SET LIBRARY TO &amp;lcOldLibrary
RETURN</FONT></CODE></PRE>
  <H2>Things I learned the hard way about using Windows API functions </H2>
  <P>If the function declaration calls for a value to be passed by reference, 
  you <I>must</I> use a variable and preface it with the "@" symbol. I thought 
  that for the buffer length, I could set a variable with the length of the 
  buffer, then just pass the variable, but not in this case. I still had to use 
  the "@" symbol.</P>
  <P>If you're using the Visual FoxPro calling convention with the DECLARE 
  command, the Windows API function names are case-sensitive.</P>
  <P>Always remember to check the return value for any error codes. 
  Unfortunately, I didn't have enough space in this article to go into detail 
  about handling errors, but at the very least you should determine what the 
  function returns when it's successful and test for that. Don't forge ahead in 
  your code just <I>assuming</I> that the API function executed 
successfully.</P>
  <H2>Conclusion</H2>
  <P>FoxPro for Windows and Visual FoxPro provide a rich programming language 
  that allows the developer to create applications of amazing power and 
  complexity. However, even with all the commands included, there are still 
  times when a task either can't be accomplished with native FoxPro code, or the 
  overhead associated with the procedure written in native FoxPro causes too 
  great a performance hit. When you hit a brick wall in your development and 
  FoxPro just won't cooperate, take time to browse through the Windows API help 
  file (included with the Professional Edition of Visual FoxPro and other 
  Microsoft "visual" development products). You may find just what you need.</P>
  <P>Having easy access to around 75 percent of the Windows API functions (the 
  rest require abstract data types such as C structures so you have to either be 
  very tricky or write C routines to access them), opens up a world of 
  possibilities for developers who do a little research. I hope these examples 
  help you, and let you build on what I've presented here. I look forward to 
  comments, questions or suggestions. </P>
  <P align=center><A href="http://www.pinpub.com/foxtalk/";><IMG border=0 
  height=72 
  src="mhtml:mid://00000220/!http://msdn.microsoft.com/library/periodic/period96/D1/Pinnacle.gif"; 
  width=216></A></P>
  <P align=center><STRONG>To find out more about FoxTalk and Pinnacle 
  Publishing, visit their website at</STRONG> <BR><A 
  href="http://www.pinpub.com/foxtalk/";><STRONG>http://www.pinpub.com/foxtalk/</STRONG></A></P>
  <P align=center><FONT face="Verdana, Arial, Helvetica" size=2>Note: This is 
  not a Microsoft Corporation website. <BR>Microsoft is not responsible for its 
  content.</FONT></P>
  <P><I>This article is reproduced from the February 1996 issue of 
  </I>FoxTalk<I>. Copyright 1995, by Pinnacle Publishing, Inc., unless otherwise 
  noted. All rights are reserved. </I>FoxTalk<I> is an independently produced 
  publication of Pinnacle Publishing, Inc. No part of this article may be used 
  or reproduced in any fashion (except in brief quotations used in critical 
  articles and reviews) without prior consent of Pinnacle Publishing, Inc. To 
  contact Pinnacle Publishing, Inc., please call (800)788-1900 or 
  (206)251-1900.</I></P></FONT><A 
  href="http://msdn.microsoft.com/isapi/gomscom.asp?TARGET=/misc/cpyright.htm"; 
  target=_top>© 1999 Microsoft Corporation. All rights reserved. Terms of 
  use</A></FONT></BLOCKQUOTE></BODY></HTML>
</x-html>Content-Type: image/gif;
	name="mlibfram.gif"
Content-Location: http://msdn.microsoft.com/library/images/msdn/art/mlibfram.gif

Attachment Converted: "c:\eudora\attach\mlibfram.gif"
Content-Type: image/gif;
	name="Pinnacle.gif"
Content-Location: http://msdn.microsoft.com/library/periodic/period96/D1/Pinnacle.gif

Attachment Converted: "c:\eudora\attach\Pinnacle.gif"