⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 windows.htm

📁 对于学习很有帮助
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">

<HTML>
<HEAD>
	<TITLE>UDDF - Windows</TITLE>
	<META NAME="Description" CONTENT="Windows 95 and NT section of the Delphi Developers FAQ" >
	<META NAME="KeyWords" CONTENT="" >

</HEAD>

<BODY  bgcolor="#FFFFFF">
<CENTER>
<IMG SRC="../images/uddf.jpg"> </CENTER>
<HR SIZE="6" color="#00FF00">

<CENTER><FONT SIZE="7" FACE="Arial Black" COLOR="RED">Windows</FONT></CENTER>
<P><H1><A NAME="windows0">???? Data segment too large ????</P></A></H1>
<P><I>From: info@sundialservices.com (Sundial Services)</I></P>

<PRE>In article &lt;325B6BAB.7096@hec.unil.ch&gt; Jean-Luc Nicoulin &lt;Jean-Luc.Nicoulin@hec.unil.ch&gt; writes:

I get the message 'Data segment too large'. What is the matter and what
can I do to solve the problem ?
</PRE>
<P>In a Windows 3.1 application, three major data-areas share one(!) 64K memory  segment:  t
he stack, the Windows 'local heap', and the data-segment containing all globals and initialized constants. 
 This area can become used up extremely quickly.</P>

<P>Consequently, W3.1 applications store almost -nothing- in the stack or in a global.  
Rather, they store -pointers- to them.  This is why, in Delphi, 'an object is a pointer.'</P>

<P>What you have to do is to comb your application looking for large globals and to 
move those into a common data block which your program allocates on startup (as an object) and destroys when done.  
You can see a lot about what's in the data segment by setting the 'linker map' to 'detailed' and looking for the 'DATA' segment.  
Whatever's in that segment is going to be trying to occupy space in the lower part of that 64K-memory segment.</P>

<P><H1><A NAME="windows1">Port command and win95, a summary.</P></A></H1>
<P><I>From: Martin Larsson &lt;martin.larsson@delfi-data.msmail.telemax.no&gt;</I></P>


<H2>APPOLOGY</H2>
<P>This was supposed to be a quick summary. It ended up being quite long. Hope it's not too boring...</P>


<H2>THE PROBLEM</H2>
<P>Under MS-DOS, an application has control of the entire machine. 
This gives the programmer a lot of freedom. To maximize speed, you can access the hardware directly if necessary.</P>

<P>Under Windows 3.x, this freedom was somewhat limited.
 You were no longer allowed to write directly to the screen, among other things. 
The problem is obvious: since the user could have any number of applications running,
 there was no guarantee that they were not accessing the same hardware simultaneously.</P>

<P>Another problem that showed up was that you had to be nice to the other applications running at the same time. 
Win 3.x is co-operatively multitasked, meaning that each application determines when it's done and other applications can run. 
Hogging the CPU for longer periods of time was not considered nice.</P>

<P>But the fact that no applications would run unless we as programmers said so, 
could be worked to our advantage when accessing the hardware. 
Since the application were guaranteed full control over the machine for as long as it wished, it could,
 when it got the CPU, muck with the I/O ports or memory, but not give up control until it was done.</P>

<P>Unfortunately, progress caught up with us; now there's Win32 (Windows NT and Windows 95). T
hese are true operating systems, with true pre-emptive multi-tasking. Each thread (the execution  unit) 
gets a certain amount of time with the processor. When the  time is up, or a thread with higher priority 
comes along, the system will switch to the next thread, even though the first  thread is not done. This 
switching can occur between any two  assembly instructions; there's no guarantee that a thread will be 
able to complete any number of instructions before it's pre-empted, and there might be a long time 'till the next timeslot.</P>

<P>This brings up a real problem with direct hardware access. A typical I/O read, for instance, is composed of several assembly  instructions:</P>

<HR><PRE>        mov dx, AddressPort
        mov al, Address
        out dx, al
        jmp Wait
    Wait:
        mov dx, DataPort
        in  al, dx
</PRE><HR>
<P>While the state of all registers are preserved on a thread-switch,  the state of the I/O ports are not. 
So, it is very possible that three applications have their way with 'your' I/O port between the 'out' and the 'in' instructions above.</P>

<H2>THE DOCUMENTED WAY</H2>
<P>The solution to this problem is to somehow tell all other applications that "Currently MyProg is using port 546, 
and everybody else better stay in line." What's needed is a mutex. Unfortunately, to use a mutex, all applications 
have to agree on a name for that mutex. But even if that was possible, you'd easily get into some thorny problems. 
Consider two applications App1 and App2. Both wants to execute the above code. Unfortunately, they're created
 by different people with different views, so App1 asks for the AddressPortMutex first, while App2 asks for the 
DataPortMutex first. And, by a sad coincidence, App1 gets the AddressPortMutex, then the system swithes to App2, 
which aquires the DataPortMutex, and we're deadlocked. App2 can't get the address port, 'cause App1 has that. 
App1 can't get the data port, 'cause App2 has that. And we're still waiting...</P>

<P>The correct way to solve this problem is to create a device driver  that owns the port/memory area. Access to
 the hardware is supported through an API. A typical function would be</P>

<HR><PRE>GetIOPortData(AddressPort, DataPort : word) : Byte;</PRE><HR>

<P>GetIOPortData would aquire a mutex that protects both (possibly all) ports, then access 
the ports, and finally releasing the mutex before returning to the caller. If different threads are calling 
this function at the same time, one will get there first, the others must wait.</P>

<P>Writing a device driver is not easy. It must be done in assembler or C, and they are really hard to 
debug. And just to be safe, a device driver for Windows 95 (a VxD) isn't compatible with a device driver for 
Windows NT (a VDD, for virtual device driver). They are said to converge, and Windows NT 6.0 and Windows 
2000 might have compatible device drivers, but until then, we're stuck with writing two separate pieces of code.</P>

<P>For more info see (for instance):</P><DIR>
<P>   Microsoft's Windows 95 Device Driver Kit</P>
<P>   Microsoft's Windows NT Device Driver Kit</P>
<P>   Microsoft Press' "Systems Programming for Windows 95" by Walter Oney</P>
</DIR>
<P>Also, check out Vireo's VtoolsD library for writing VxD's in C. <A HREF="http://www.vireo.com/">http://www.vireo.com/</A>.</P>



<H2>THE UNDOCUMENTED WAY</H2>
<P>The above problem isn't too real. An application that accesses the hardware directly, 
is usually using some specialized hardware. A machine-configuration like that tend to run one application only, 
who's sole purpose is to access that hardware. In such a scenario, writing a device driver seems too much trouble. After all, the reason 
the thing is running on Windows, is just to get the nice GUI for (almost) free, not that 10 applications can be running simultaneously.</P>

<P>Fortunately, Windows 95 is built to be compatible with Windows 3.x. This means that direct I/O must be allowed, simply because a 
lot of Win 3.x programs uses it. To access the I/O ports, simply step down to assembly. The following code was supplied by Arthur Hoornweg
 (hoornweg@hannover.sgh-net.de):</P>

<HR><PRE>    function getport(p:word):byte; stdcall;
    begin
      asm
         push edx
         push eax
         mov  dx,p
         in   al,dx
         mov  @result,al
         pop  eax
         pop  edx
      end;
    end;


    Procedure Setport(p:word;b:byte);Stdcall;
    begin
      asm
        push edx
        push eax

        mov dx,p
        mov al,b
        out dx,al

        pop  eax
        pop  edx
      end;
    end;
</PRE><HR>

<P>Fran&ccedil;ois Piette also has some direct I/O access functions at <A HREF="http://rtfm.netline.be/fpiette/portiofr.htm">http://rtfm.netline.be/fpiette/portiofr.htm</A></P>


<H2>BUT WHAT ABOUT NT?</H2>
<P>The above will not work on Windows NT. NT is a much more robust operating system, and allowing all and everybody access 
to the hardware anytime they wanted, would seriously endager the stability. In addition, NT is cross platform, and access to I/O ports might 
be wildly different on different processors.</P>

<P>Even so, it is possible to access the I/O ports directly under NT on x86 processors. This is highly undocumented, and will probably 
disappear in future versions of the operating system.</P>

<P>I have not much information on the process, but an article by D. Roberts in the May, 1996 issue of Dr. Dobb's Journal looks  promising: 
"Direct Port I/O and Windows NT." This seems to be the only DDJ I'm missing, so I can't verify it. 
See <A HREF="http://www.ddj.com">http://www.ddj.com</A> for ordring of back-issues.</P>

<P>Windows Developer's Journal does have an article on "Port I/O under Windows." 
It's written by Karen Hazzah, and appeared in the June 1996 issue. See <A HREF="http://www.wdj.com">http://www.wdj.com</A> for ordering of back-issues.</P>

<H2>RESOURCES</H2>
<P>(Note, I know very little about these resources, check them out yourself.)</P>

<P>There are newsgroups dedicated to the topic of writing VxD's and VDD's:</P> <DIR>
<P>comp.os.ms-windows.programmer.nt.kernel-mode  (VDD)</P>
<P>comp.os.ms-windows.programmer.vxd             (VxD)</P>
</DIR>

<P>Dejanews (<A HREF="http://www.dejanews.com">http://www.dejanews.com</A>) turned up quite a few hits on 'device driver direct I/O access 95'.</P>

<P>BlueWater Systems have developed OCX's for direct I/O, memory access  and interrupt handling under all Win32 platforms. 
They also seem to offer custom built device drivers. See their page at <A HREF="http://www.bluewatersystems.com/">http://www.bluewatersystems.com/</A>.</P>

<P>I know some other company has been advertising here for their ability to write custom VxD's. But I can't find that reference.</P>

<P><H1><A NAME="windows2">Read the Run Minimized  Checkbox</P></A></H1>
<H2> Solution 1 </H2>
<PRE>Paul S. Knapp wrote:
>
> Does anyone know how to make as Delphi app read the Run Minimized
> checkbox in the Windows 3.1 or 3.11 StartUp Group.
>
> I cannot get my application to run minimized when this checkbox is
> checked.  I would like to be able to give my users the option of
> starting the application in their startup group, in either maximized or
> minimized mode.  Every Windows application I have ever used is able to
> start in the mode selected by the checkbox in the Startup Group. I
> assume Delphi applications should be able to as well, but so far I a
> haven't found a way.
>
> Thanks in advance for your advice
> Paul Knapp
</PRE>

<P>Hi Paul!</P>

<P>Use WinProcs unit and after created main form add call ShowWindow.</P>
<P>You can use HInstance, HPrevInst, CmdShow and CmdLine global variables.</P>

<HR><PRE>program Project1;

uses
  WinProcs, {*** use WinProcs}
  Forms,
  Unit1 in 'UNIT1.PAS' {Form1};

{$R *.RES}

begin
  Application.CreateForm(TForm1, Form1);
  ShowWindow(Form1.handle, CmdShow);
  Application.Run;
end.
</PRE><HR>

<H2> Solution 2</H2>
<P><I>From: Ken Kyler &lt;ken@kyler.com></I></P>

<P>Here's and example, it's taken from</P>

<P><I>Rubenking, Neil (1996).  _Delphi Programming Problem Solver_.     Foster City, CA: IDG Books.  ISBN:1-56884-795-5.</I></P>

<HR><PRE>unit Unit1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    ShowHow : word ;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  SUI : TStartupInfo ;
begin
  if CmdShow = SW_SHOWDEFAULT then
  begin
    GetStartupInfo( SUI ) ;
    ShowHow := SUI.wShowWindow ;
  end
  else
    ShowHow := CmdShow ;

  if ShowHow = SW_SHOWMAXIMIZED then
    WindowState := wsMaximized ;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  case ShowHow of
    SW_SHOWMINIMIZED,
    SW_MINIMIZE,
    SW_SHOWMINNOACTIVE :
      Application.Minimize ;
  end ;
end;

end.
</PRE><HR>

<h2>Solution 3</h2>
<i>From: a.viebke@berlin.snafu.de (Andreas Viebke)</i><p>

This works with NT 4 and Delphi 2.01. It took me one and a half hours
to find out:

Make your project code look like this:

<hr><pre>  begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Form1.Show;
    Application.Minimize;
    Application.Run;
  end.</pre><hr>

It seems to be important that neither OnCreate nor OnShow is disturbed
by a procedure that changes a window's state.


<P><H1><A NAME="windows3">Shared memory in a DLL with Delphi 2.0</P></A></H1>
<P><I>From: johnnysc@ix.netcom.com (John Crane)</I></P>

<P>Sharing Memory Mapped Files...  Check out the following code:</P>

<HR><PRE>var
  HMapping: THandle;
  PMapData: Pointer;

const
  MAPFILESIZE = 1000;

procedure OpenMap;
var
  llInit: Boolean;
  lInt: Integer;
begin
  HMapping := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, MAPFILESIZE, pchar('MY MAP NAME GOES HERE'));
  // Check if already exists
  llInit := (GetLastError() &lt;> ERROR_ALREADY_EXISTS);
  if (hMapping = 0) then begin
    ShowMessage('Can''t Create Memory Map');
    Application.Terminate;
    exit;
  end;
  PMapData := MapViewOfFile(HMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  if PMapData = nil then begin
    CloseHandle(HMapping);
    ShowMessage('Can''t View Memory Map');
    Application.Terminate;
    exit;
  end;
  if (llInit) then begin
    // Init block to #0 if newly created
    memset(PMapData, #0, MAPFILESIZE);
  end;
end;

procedure CloseMap;
begin
  if PMapData &lt;> nil then begin
    UnMapViewOfFile(PMapData);
  end;
  if HMapping &lt;> 0 then begin
    CloseHandle(HMapping);
  end;
end;
</PRE><HR>
<P>Any two or more applications or DLLs may obtain pointers to the same physical block of memory this way.    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -