📄 g-po.gml
字号:
Some places where pointer conversion may be required are:
.* .ix 'LocalLock pointer conversion'
.* .ix 'GlobalLock pointer conversion'
.* .ix 'lParam pointer conversion'
.* .ix 'pointer conversion' 'LocalLock'
.* .ix 'pointer conversion' 'GlobalLock'
.* .ix 'pointer conversion' 'lParam'
.begbull $compact
.bull
LocalLock
.bull
GlobalLock
.bull
the lParam in a window callback routine (if it is a pointer)
.endbull
.*
.section When To Convert Outgoing Pointers
.*
.np
.ix 'Windows 3.x extender' 'pointer conversion'
Typically, there is no need to do any kind of conversions on your
pointers when passing them to Windows.
The Supervisor handles all 32-bit to 16-bit translations for you, in
the case of the regular Windows API functions.
However, if you are passing a 32-bit pointer to some other 16-bit
application in the Windows environment, then pointer conversions must
by done.
There are two types of "outgoing" pointers: data pointers and function
pointers.
.np
Function pointers (to callback routines) must have a thunking layer
provided, using the
.kw GetProc16
function (this is explained in detail in a later section).
.np
Data pointers can be translated from 32-bit to 16-bit using the
.kw AllocAlias16
and
.kw AllocHugeAlias16
functions.
These functions create 16-bit far pointers that have the same linear
address as the 32-bit near pointer that was converted.
.np
It is important to remember that when passing a pointer to a data
structure in this fashion, any pointers in the data structure must
also be converted.
.np
The Supervisor will convert any pointers that it knows about; but
there are some complications created by the fact that Windows allows
you to pass pointers in functions that are prototyped to take a long
integer.
.np
The Windows API functions
.kw SendMessage
and
.kw SendDlgItemMessage
rely on other fields determining the nature of the long data item that
they accept; this is discussed in detail in the next section.
.beglevel
.*
.section SendMessage and SendDlgItemMessage
.*
.np
.kw SendMessage
and
.kw SendDlgItemMessage
have special cover functions that determine when the
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
long
.do end
.if '&lang' eq 'FORTRAN 77' .do begin
32-bit
.do end
integer is really a pointer and needs to be converted.
These cover functions are used automatically, unless the macro
.kw NOCOVERSENDS
is defined before including
.if '&lang' eq 'FORTRAN 77' .do begin
.ix 'WINAPI.FI'
.fi WINAPI.FI
as in the following example.
.millust begin
*$define NOCOVERSENDS
*$include winapi.fi
.millust end
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.ix 'WINDOWS.H'
.fi WINDOWS.H
as in the following example.
.millust begin
#define NOCOVERSENDS
#include <windows.h>
.millust end
.do end
.np
.kw SendMessage
and
.kw SendDlgItemMessage
will do pointer conversions automatically using
.kw AllocAlias16
and
.kw FreeAlias16
(unless
.kw NOCOVERSENDS
is defined) for the following message types:
.begbull $compact
.bull
combo boxes (CB_ messages)
.bull
edit controls (EM_ messages)
.bull
list boxes (LB_ messages)
.bull
certain windows messages (WM_ messages);
.endbull
.np
The messages that are intercepted by the cover functions for
.kw SendMessage
and
.kw SendDlgItemMessage
are:
.millust begin
CB_ADDSTRING CB_DIR CB_FINDSTRING
CB_FINDSTRINGEXACT CB_GETLBTEXT CB_INSERTSTRING
CB_SELECTSTRING
EM_GETLINE EM_GETRECT EM_REPLACESEL
EM_SETRECT EM_SETRECTNP EM_SETTABSTOPS
LB_ADDSTRING LB_DIR LB_FINDSTRING
LB_FINDSTRINGEXACT LB_GETITEMRECT LB_GETSELITEMS
LB_GETTEXT LB_INSERTSTRING LB_SELECTSTRING
LB_SETTABSTOPS
WM_MDICREATE WM_NCCALCSIZE
.millust end
.np
Note that for
.kw SendMessage
and
.kw SendDlgItemMessage,
some of the messages may NOT require pointer conversion:
.begbull
.bull
CB_ADDSTRING, CB_FINDSTRING, CB_FINDSTRINGEXACT, CB_INSERTSTRING
will not need a conversion if the combo box was created
as owner-draw style without CBS_HASSTRINGS style.
.bull
LB_ADDSTRING, LB_FINDSTRING, LB_FINDSTRINGEXACT, LB_INSERTSTRING
will not need a conversion if the list box was created
as owner-draw style without LBS_HASSTRINGS style.
.endbull
.np
The macro
.kw NOCOVERSENDS
should be defined in modules where messages like these are being sent.
With these messages, the lParam data item does not contain a pointer,
and the automatic pointer conversion would be incorrect.
By doing
.if '&lang' eq 'FORTRAN 77' .do begin
.millust begin
*$define NOCOVERSENDS
*$include winapi.fi
.millust end
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.millust begin
#define NOCOVERSENDS
#include "windows.h"
.millust end
.do end
.pc
modules that send messages like the above will not have the pointer
conversion performed.
.endlevel
.*
.section GlobalAlloc and LocalAlloc
.*
.np
The functions
.kw GlobalAlloc
and
.kw LocalAlloc
are the typical way of allocating memory in the 16-bit Windows
environment.
In the 32-bit environment, there is no need to use these functions.
The only time
.kw GlobalAlloc
is needed is when allocating shared memory, i.e.,
.kw GMEM_DDESHARE.
.if '&lang' eq 'FORTRAN 77' .do begin
.np
The
.kw ALLOCATE
and
.kw DEALLOCATE
statements can be used to allocate memory from
your 32-bit near heap.
By allocating memory in this way, you may create data objects as large
as the enhanced mode Windows memory manager will permit.
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.np
The C runtime functions
.kw malloc
and
.kw free
manipulate your 32-bit near heap for you.
By using these functions to allocate memory, you may create data
objects as large as the enhanced mode Windows memory manager will
permit.
.do end
.*
.section Callback Function Pointers
.*
.np
To access a callback function, an instance of it must be created using
.kw MakeProcInstance.
This creates a "thunk" (a special piece of code) that automatically
puts the application's data segment into the AX register, and then
calls the specified callback function.
.np
In Windows 3.x, it is not possible to do a
.kw MakeProcInstance
directly on a 32-bit callback routine, since Windows 3.x does not understand
32-bit applications.
Therefore, it is necessary to use a 16-bit callback routine that
passes control to the 32-bit callback routine.
This 16-bit callback routine is automatically created by the Supervisor
when using any of the standard Windows API functions that accept a
callback routine.
.np
The 16-bit callback routine for a 32-bit application is a special
layer that transfers the parameters from a 16-bit stack to the 32-bit
stack, and then passes control to 32-bit code.
These 16-bit callback routines are found in the Supervisor.
The function
.kw GetProc16
provides pointers to these 16-bit callback routines.
.np
However, it is not often necessary to use the
.kw GetProc16
function to obtain a 16-bit/32-bit callback interface function.
.np
In the general case, one would have to write code as follows:
.if '&lang' eq 'FORTRAN 77' .do begin
.millust begin
integer*4 pCb, fpProc
pCb = GetProc16( A_Function, GETPROC_callbacktype )
fpProc = MakeProcInstance( pCb, hInstance )
* do stuff
call Do_it( ..., fpProc, ... )
* do more stuff
call FreeProcInstance( fpProc )
call ReleaseProc16( pCb )
.millust end
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.millust begin
#define NOAUTOPROCS
#include <windows.h>
CALLBACKPTR pCb;
FARPROC fpProc;
pCb = GetProc16( A_Function, GETPROC_callbacktype );
fpProc = MakeProcInstance( pCb, hInstance );
/* do stuff */
Do_it( ..., fpProc, ... );
/* do more stuff */
FreeProcInstance( fpProc );
ReleaseProc16( pCb );
.millust end
.do end
.np
It is not necessary to use this general code in the case of the
regular Windows API functions.
The following functions will automatically allocate the correct
16-bit/32-bit callback interface functions:
.begbull $compact
.bull
ChooseColor
.bull
ChooseFont
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.bull
CorrectWriting
.do end
.bull
CreateDialog
.bull
CreateDialogIndirect
.bull
CreateDialogIndirectParam
.bull
CreateDialogParam
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.bull
DdeInitialize
.do end
.bull
DialogBox
.bull
DialogBoxIndirect
.bull
DialogBoxIndirectParam
.bull
DialogBoxParam
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.bull
DictionarySearch
.do end
.bull
EnumChildWindows
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.bull
EnumFontFamilies
.do end
.bull
EnumFonts
.bull
EnumMetaFile
.bull
EnumObjects
.bull
EnumProps
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.bull
EnumSymbols
.do end
.bull
EnumTaskWindows
.bull
EnumWindows
.bull
Escape (SETABORTPROC option)
.bull
FindText
.bull
GetOpenFileName
.bull
GetSaveFileName
.bull
GlobalNotify
.bull
GrayString
.bull
LineDDA
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.bull
mciSetYieldProc
.bull
mmioInstallIOProc
.bull
NotifyRegister
.do end
.bull
PrintDlg
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.bull
ProcessWriting
.bull
Recognize
.bull
RecognizeData
.do end
.bull
RegisterClass
.bull
ReplaceText
.bull
SetClassLong (GCL_WNDPROC option)
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.bull
SetPenHook
.do end
.bull
SetResourceHandler
.bull
SetTimer
.bull
SetWindowLong (GWL_WNDPROC option)
.bull
SetWindowsHook
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.bull
SetWindowsHookEx
.bull
TrainInk
.do end
.endbull
.np
As well, the following functions are covered to provide support
for automatic creation of 16-bit callback routines:
.begbull $compact
.bull
FreeProcInstance
.bull
MakeProcInstance
.bull
UnhookWindowsHook
.endbull
.np
If you need to get a callback that is not used by one of the above
functions, then you must code the general case.
Typically, this is required when a DLL needs a callback routine.
In modules where this is necessary, you define the macro
.kw NOAUTOPROCS
before you include
.if '&lang' eq 'FORTRAN 77' .do begin
.fi WINAPI.FI
as in the following example.
.millust begin
*$define NOAUTOPROCS
*$include winapi.fi
.millust end
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.fi WINDOWS.H
as in the following example.
.millust begin
#define NOAUTOPROCS
#include <windows.h>
.millust end
.do end
.np
Be careful of the following when using
.kw NOAUTOPROCS.
.autonote
.note
The call to
.kw MakeProcInstance
and
.kw FreeProcInstance
for the callback function occurs in a module with
.kw NOAUTOPROCS
defined.
.note
No Windows API functions (listed above) are used in the module with
.kw NOAUTOPROCS
defined.
If they are, you must code the general case to use them.
.endnote
.np
Note that
.kw NOAUTOPROCS
is in effect on a module-to-module basis only.
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.np
You can avoid using
.kw NOAUTOPROCS
on a call-by-call basis, if you do the following:
.millust begin
#undef <function>
<function>
Note: re-defining is only needed if you want to
use a covered version of the function later on.
#define <function> _Cover_<function>
.millust end
.np
For example:
.millust begin
{
#undef SetWindowsHook
#undef MakeProcInstance
FARPROC fp,oldfp;
CALLBACKPTR cbp;
.millust break
cbp = GetProc16( CallbackHook, GETPROC_CALLBACK );
fp = MakeProcInstance( cbp, hInstance );
oldfp = SetWindowsHook( WH_CALLWNDPROC, fp );
}
.millust end
.np
This allows you to add general case code in the same module, without having
to break the module into two parts.
.do end
.np
RegisterClass automatically does a GetProc16 for the callback function,
unless the macro NOCOVERRC is specified before including
.if '&lang' eq 'FORTRAN 77' .do begin
.fi WINAPI.FI
as in the following example.
.millust begin
*$define NOCOVERRC
*$include winapi.fi
.millust end
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.fi WINDOWS.H
as in the following example.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -