📄 ch01.htm
字号:
DispatchMessage(&Msg);
}
return Msg.wParam;
}
//////////////////////////////////////
// Register the window
//////////////////////////////////////
BOOL Register(HINSTANCE hInst)
{
/* You can use WNDCLASSEX and RegisterClassEx with
WIN32 */
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInst;
WndClass.hIcon =
LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
return
(RegisterClass(&WndClass) != 0);
}
//////////////////////////////////////
// Create the window
//////////////////////////////////////
#include <wtypes.h>
__RPC_FAR Sam()
{
return 0;
}
HWND Create(HINSTANCE hInstance, int
nCmdShow)
{
HWND hWindow = CreateWindowEx(0, szAppName, szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL,
hInstance, NULL);
if (hWindow == NULL)
return hWindow;
ShowWindow(hWindow, nCmdShow);
UpdateWindow(hWindow);
return hWindow;
}
// =====================================
// IMPLEMENTATION
// =====================================
#define Window1_DefProc DefWindowProc
void Window1_OnDestroy(HWND hwnd);
//////////////////////////////////////
// The window proc is where messages get processed
//////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWindow,
UINT Message,
WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
HANDLE_MSG(hWindow, WM_DESTROY, Window1_OnDestroy);
default:
return Window1_DefProc(hWindow, Message, wParam, lParam);
}
}
//////////////////////////////////////
// Handle WM_DESTROY message
//////////////////////////////////////
#pragma argsused
void Window1_OnDestroy(HWND hwnd)
{
PostQuitMessage(0);
}
</FONT></PRE>
<P>This program looks like, and indeed is, an
old-fashioned Windows program from
back before the days of the object frameworks such as OWL or the VCL. It will, however,
compile unchanged in BCB. In fact, I did not have to change any of the code or any
of BCB's compiler settings in order to create
this program.</P>
<P>To get started producing this code from scratch, open up BCB and start a new project.
Go to View | Project Manager and remove <TT>Unit1</TT> from the project. Now save
the file to a directory created specifically for this program.
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>TIP:</B></FONT><B> </B>I believe you should always create
unique directories for each program you create. If you do not take this step, you
will never be able to keep the files
from this program sorted from files used by
other programs you create. To not put a BCB project in its own directory is to go
face to face with the forces of chaos.
<HR>
</BLOCKQUOTE>
<P>Go to the View menu again and choose the Project Source
menu item. Strip out all
the code created for you by BCB and replace it with the code shown above. You are
taking control of this project and don't need any help from the BCB or its rudimentary
code generation processes.</P>
<P>In the next chapter I
will explain in some depth why BCB should not be considered
a code generator, a CASE tool, or anything of the kind. I do, however, feel that
BCB is primarily an IDE-oriented tool. In this one case, it would not matter much
whether you wrote the code
inside the IDE or from the command line. However, BCB
code is meant to be written, and your programs are meant to be designed, inside the
IDE.</P>
<P>This is not the place to get into a lengthy explanation of how the WinAPICode
program works. If you
are truly curious, it is taken nearly verbatim from one of
the early chapters of my book called Teach Yourself Windows 95 Programming, published
by Sams Publishing. That book covers raw Windows API programming, which is an invaluable
skill, even for
BCB RAD programmers. However, unraveling the secrets of the Windows
API is not the goal of this current book, so I will merely point out a few key passages
from the program.</P>
<P>The following code shows the message loop for the WinAPICode
program:</P>
<PRE><FONT COLOR="#0066FF">while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
</FONT></PRE>
<P>This is the engine that drives the program, but it is unlike any of the code you
see in a standard BCB program. It is not, however, any different from the message
loop that appears inside the VCL. I will show you how to step into the code that
contains that loop in Chapter 2.</P>
<P>At first, the following code also looks
completely foreign to the BCB paradigm:</P>
<PRE><FONT COLOR="#0066FF">LRESULT CALLBACK WndProc(HWND hWindow, UINT Message,
WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
HANDLE_MSG(hWindow,
WM_DESTROY, Window1_OnDestroy);
default:
return Window1_DefProc(hWindow, Message, wParam, lParam);
}
}
</FONT></PRE>
<P>It would, however, be a mistake to assume the VCL knows nothing about Windows
procedures. In fact, you can add
code to your BCB programs that gets called every
time the <TT>WndProc</TT> for your program or any of its forms gets called. Once
again, I am in danger of wandering too far afield, but if you open up <TT>Forms.hpp</TT>
from the <TT>include/VCL</TT>
directory, you will find the following declaration:</P>
<PRE><FONT COLOR="#0066FF">virtual void __fastcall WndProc(Messages::TMessage &Message);
</FONT></PRE>
<P>This call is one of the methods of <TT>TForm</TT>. As you can see, it is declared
virtual, so you can override it in any of your own programs if you want. By doing
so, you place yourself directly inside the window procedure for your form. This is
an extremely powerful technique, but is one that most programmers will never need
to
utilize. However, it is good to know that it is available if you need it. I give
an example of how to override this method in Chapter 4.
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The
<TT>TMessage</TT> structure
that is passed to the <TT>WndProc</TT> method of <TT>TForm</TT> contains all the
fields that are passed to a standard Windows procedure:</P>
<PRE><FONT COLOR="#0066FF">struct TMessage
{
unsigned int Msg;
union
{
struct
{
unsigned short WParamLo;
unsigned short WParamHi;
unsigned short LParamLo;
unsigned short LParamHi;
unsigned short ResultLo;
unsigned short ResultHi;
};
struct
{
long
WParam;
long LParam;
long Result;
};
};
};</FONT></PRE>
</BLOCKQUOTE>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<BLOCKQUOTE>
<P>All the information is there, if you need it. However, my point is that there
are few cases in
BCB programming in which it is necessary to get down to this level.
Once again, this subject will be taken up later in greater depth. In particular,
I discuss <TT>TMessage</TT> and related structures in Chapter 4.
<HR>
</BLOCKQUOTE>
<P>In this
section of the chapter, I have shown that BCB allows you to get down to
the raw Windows API level if you want. There is, of course, nothing involving the
Windows API you cannot do in BCB, just as there was nothing involving the Windows
API that you
could not do in either BC5 or Delphi. It would be silly and fruitless
to try to hunt for exceptions. Callbacks, pointers to pointers, COM, whatever it
is you want to do; BCB is up to the challenge. My point in this section is simply
to show the great
technical depth of this product.
<H3><A NAME="Heading38"></A><FONT COLOR="#000077">The DynamicButton Program</FONT></H3>
<P>The Dynam
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -