There was an idea here to congratulate our chief accountant in a more or less original way, for example, with the help of her favorite 1C program? But how?
After some thought, the idea came to use for background congratulations the background image in the client area of conventional forms for configurations on 1C77-1C82 or in the external window for managed forms 1C82 and in all cases for 1C83. On it, display the desired message and give links to the congratulatory video, as shown in the figure.
Part One - Resulting
Obviously, this idea is not new. So, in 2011, a
similar solution was proposed based on
FormEx.dll, by Aleksey Fedorov aka ALF . And questions on
how to achieve this were asked back in 2008.
At one time, we also used this component to load the background image in 1C77. But downloading large bmp-files (and others could not be used) was slow (because of this, small pictures laid with tiles were used), so there was a desire to write your own external component (VK), which will only download the necessary images and nothing more, unless what else to be some testing ground for experiments.
Such a component was written (also, only for bmp-files, using, if necessary, tiling). The
WinAPI LoadImage () function was used there. This dll did not conflict with FormEx.dll, it was simple, fast enough and served for a long time.
All this was wonderful, but it was time to expand its capabilities, and here a different approach was needed.
In this article, we do not address the issues of creating multimedia files. This is not our specialty. We restrict ourselves only to some nuances of programming external components for 1C.
1C77
Since the versions of the 1C platform can be different, there can be several solutions. In our case, these were configurations on 1C77 (Fig. 1).
Fig. 1. Congratulatory image in the test configuration on 1C77.
The video here, although its own, but the idea of its creation is gleaned from
Anna Shiyanova, under the nickname "Special case" . This girl has talent, she can be imitated, but it is hardly possible to completely repeat the style. In this case, I just wanted at least some element of creativity.
If one of the colleagues is already tired of looking at other people's congratulations, then they can overload the picture by “
Alt + I ” (Fig. 2-3).
Fig. 2. Selecting a different background image in the "File / Select Background" menu or by "Alt + I".
And at the same time see the information about the module used by "
Alt + L " (Fig. 3).
Fig. 3. Overloaded background image along with information about the program ("Help / About the LionExt32.dll module" or "Alt + L").
1C82 conventional forms
Naturally, the majority are now oriented toward the G8 (1C8x). However, working with the background image in 1C is possible only on ordinary forms in version 8.2 and less, and if you do not use any processing that starts in the “desktop” mode, which will simply completely overlap our background (Fig. 4).
Fig. 4. Congratulatory image in the test configuration on the usual forms 1C82.
Note that the links to Fig. 4 indicate not our video. They are shown just for the test.
In ordinary forms, 1C82 no longer provides the standard way to access the menu, since it is not systemic there, as in the "seven", but "own" (although the system can be created, but why do we need two main menus?). However, hotkeys can be used. Therefore, “Alt + I”, in our component, we invoke a dialog, as in Fig. 2, and load a different background (Fig. 5).
Fig. 5. Overloaded background image in “thick” 1C82 forms.
Similarly, you can get information about the module by pressing the "Alt + L" key, as in fig. 3.
1C82 managed forms
For managed forms in 1C82, you can still find the window we need at the seventh nesting level, such as “
V8FormElement ” and draw on it, but somehow it’s not interesting.
For us, from these considerations it follows that it is easier to create an external window with a congratulatory message (Fig. 6) than to handle each individual case. The window itself can be closed, more precisely, minimized by "
Esc ", "
Ctrl + F4 ", "
Alt + F4 " or by clicking on the "
cross ".
Fig. 6. Congratulatory image in a test configuration on managed forms 1C82.
Moreover, the minimized window (Fig. 7) can be expanded again.
Fig. 7. A minimized image of the external window on managed forms 1C82.
The dimensions and relative location of the external window can be changed, everything is as usual here (see enlarged images of the external windows in Fig. 6 and Fig. 10). Note that hotkeys only work if the external window is active.
1C83 conventional forms
In 1C83 there are no more child windows at all, which can serve as a criterion for version 1C in our dll. Moreover, “thick” forms are a frame window (Fig. 8), and managed forms are frameless (Fig. 9). That is, everything that is not a frame can be redrawn. A frame can also be redrawn, but only as a system element.
Here, using a dynamic library, we created a test window and subordinated it to the main 1C window. The difference in behavior is seen in the figures.
1C83 managed forms
In the case of 1C83, as in the managed forms 1C82, we will draw our congratulations not against the background, but in a separate window, the prototype of which is shown in Fig. 8-9. As a result, the desired component (
LionExt32.dll or
LionExt64.dll ) will give the following result (Fig. 10-12).
Fig. 10. The background image in the external window for the usual forms 1C83.
Fig. 11. The background image in the external window of managed forms 1C83, release 14, 64-bit version.
Fig. 12. The background image in the external window of managed forms 1C83, release 15, 64-bit version.
Preliminary findings
This component was actually used in practice (Fig. 1), the chief accountant was satisfied, everything went wonderfully. Along the way, it turned out that users like to choose their own background pictures, in this case, to work on the "seven". For the G8, our component is adapted with a reserve for the future, while it should be considered as a demo version.
The interest here was that
this component did not require compliance with the technology of creating external components from 1C . Perhaps additional ideas will arise to expand its capabilities. For example, for configurations that are fully supported, you do not want to make changes to the 1C code without special need. In this case, one could offer the option of external loading an arbitrary dll into the address space 1C. But this is the topic of another article.
Of technical innovations, a lock was used to unload our component with the 1C platform (since it does not comply with the VK format). In addition, another trick made it possible to assign a
local menu to the child window, since the Windows operating system blocks the creation of such a menu for subordinate windows. Therefore, you will not see local menus in the same
MDI (Multi Document Interface) anywhere. He is replaced by command panels, toolbars and a context menu. There is still a moment for updating windows. Sometimes it happens that neither
UpdateWindow () nor
InvalidateRect () work properly. But a couple of functions in this case are successful:
ShowWindow(hWnd, SW_HIDE); ShowWindow(hWnd, SW_SHOW);
It should also be noted that our component may conflict with others, for example, with FormEx.dll for 1C77. In this case, it needs to be loaded last.
By the way, it is noticed that if you create a configuration in version 1C-8.3.14 and higher, the component is not loaded in any regular way. But if the database was created in an earlier version of 1C, and opens in the latest versions, then there are no problems loading our VK. This once again hints at the need to create an external bootloader.
This project uses the
WinAPI GDI + subsystem. Using it, you can display pictures of various formats:
bmp, jpg, gif, png, tif and others. In the same order, the component attempts to load the first available
Main. * File from the local
Pics directory in the current configuration. If none of these files are found, then a simple background image from component resources is used. In fig. Figure 13 shows this background image for the usual forms of 64-bit 1C83, release 15. For a change, the external window of the slang has been enlarged and another image from the
Main1.png file, which has been
tiled , has been added to its background.
Fig. 13. The default background image for the usual forms of 64-bit 1C83, release 15. In addition, another image from the Main1.png file, laid “tiling”, has been added.
Differences in the operation of the component in different bit modes are not observed.
It can also be noted that our component subclasses the main 1C window and its MDI client, if any. This, apparently, serves as a source of conflict with FormEx.dll when it is loaded last (in 1C77).
Part Two - Technical
Directly with the project itself can be found at the following links:
A
C ++ project can be easily adapted for version
10 if the string “
v120 ” is replaced by “
v100 ” in the configuration files and “
ToolsVersion =“ 12.0 ”is
replaced by “
ToolsVersion = “4.0 ”.
The code for the
32 -bit and
64 -bit versions of
1C is the same and can be compiled at the same time.
Version 1C77 is determined in the external component by the non-zero function
handle GetMenu () , and version 1C83, by the absence of child windows in the main window, the handle of which is determined by the
GetForegroundWindow () function.
About the technology of creating external components for 1C
On the ITS discs of the 1C company, and on the Internet, one can easily find information on the creation of VC and the corresponding templates in different programming languages. However, in the times of 1C77, these patterns satisfied "not only everyone."
If you look at some widely used components, especially for 1C77, you will see that their authors often used special programming methods to expand the capabilities of their designs.
Perhaps one of the first such external components was
"RAINBOW ADDIN 2000 for 1C: Enterprise 7.7 .
" Perhaps the most important here was a deeper penetration into the bowels of the "seven" than the official VK technology allowed, although it followed the VK format. This was achieved due to the received, quite possibly non-standard methods, headers (* .h-files) of 1C77 library files used in other widely known projects.
Indeed, if such 1C functions as
LoadExternalComponent () and
ConnectExternalComponent () allow you to embed
external dlls into your own address space (first of all, that satisfy the VK technology format), then why don't user programs succumb to the temptation and try to access other ones hidden from them, procedures and other objects of the target platform? This approach has just been successfully demonstrated by the
Rainbow.dll component.
Later, a similar mechanism was adopted by other authors of component 1C version 7.7. Of particular note is the component for the "seven"
1C ++. Dll and its, as it were, a special case of
FormEx.dll .
But the nontrivial approach to the design of external components for 1C77 did not end there. Apparently, someone should have said: “Why do we need a blacksmith? We don’t need a blacksmith! ” Here, by “blacksmith” we mean COM technology from MicroSoft, which, in a sense, was followed by VK technology for the “seven”. No, well, really, why do we need a registry if we download our VK directly? This may make sense for web browsers that work with the Internet, but for local operation, using the registry is clearly redundant. At the very least, this should not be a prerequisite. Moreover, for editing the registry you need administrative rights.
Note that 1C was very fond of this technology (at least until porting 1C to Linux). We treat her pretty cool. COM is convenient for using the ActiveX component and this is natural, since the latter were originally developed for the Internet.
However, in the latest versions, 1C added the ability to use the
Native API technology, which eliminates the need for a registry. In principle, this is what we need, except that this technology is not applicable in the "seven", and it, for some, is still relevant.
But sometimes relatively simple tasks arise when you do not want to use a bunch of boilerplate template code VK and it is advisable to work with 1C from the side of the external component only. As, say, in our case, the demonstration of a congratulatory image in the client area or, if necessary, in a separate window, configuration 1C.
In other words, if we are not going to directly exchange data between 1C and VK, then we will be quite happy with a simpler and more universal version of the external component for 1C. Simplicity here will be achieved due to the lack of boilerplate code.
Alternative technology for creating VK for 1C
Since VK for 1C is a special case of a
COM server (before the
Native API technology), there were VK developers who said: “COM - no!”. Particularly noticeable is the activity in this direction by
Alexander Orefkov . Its components “
1sqlite.dll ”, “
TurboMD.dll ”, and possibly others, do not use COM from the word “completely”. The
Yoksel component ("
SpreadSheet.dll ") also develops along this path.
But how then does the VK loader from 1C77 load these components? After all, they do not even try to imitate some kind of COM there. Indeed, if we try to bluntly slip some standard dll generated by, say, the
MS VC ++ wizard into the
LoadExternalComponent () function, then we will have a bummer.
In the "seven" we get a message like:
An error occurred while creating an object from the <Full Path \ Component Name> .dll component (CLSID is missing)
In the "thick" 32-bit client of the "eight" message will be similar. The same dll will cause a similar swearing (Fig. 15):
An error occurred while calling the context method (Load ExternalComponent): An error occurred while loading an external component
So still, how do the libraries mentioned solve this problem? Studying the texts of Orefkov and Yoksel programs, we ultimately come to the conclusion that the following “
magic lines ” in the resource file (* .rc or * .rc2) are “to blame”:
STRINGTABLE DISCARDABLE BEGIN 100 "\0sd" // 1sqlite.dll 100 "\0tmd" // TurboMD.dll 100 "\0f" // SpreadSheet.dll END
Those. without fail, in the program resources there is a line with identifier
100 and some string value, the first character of which is zero. You can experiment with variants of such lines, but the string "
\ 0L " is fine with me. Thus, we create a resource file and write lines like this:
STRINGTABLE DISCARDABLE BEGIN 100 "\0L" // 1 ! END
We connect this file to our simplest dll project generated by the MS C ++ wizard, add the code:
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: MessageBox(NULL, ", DllMain()!", "", MB_OK); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; }
and observe (Fig. 14).
Fig. 14. Using the simplest “VK” in 1C82.
Without "magic lines" in the resource file, our dll, after showing MessageBox, immediately unload with a curse from the 1C side (Fig. 15).
Fig. 15. Error loading regular dll in 1C82.
That is, these lines really have a magical effect on the loader of external 1C components.
The first, it seems, “magic lines” was described in his old article by
Alexei Fedorov (ALF) , but the link to it is no longer available, and the author does not see the point in its re-publication. Moreover,
Alexander Orefkov used them most intensively, and apparently, from his submission, the author was
Yoksel . Therefore, we will talk about the
“magical” lines of Fedorov-Orefkov . Their meaning is to block the unloading of non-standard (from the point of view of 1C) dll-files by the function
Load ExternalComponent () . Moreover, as we see, this technique works not only in 1C77, but also in “thick” 1C82 forms.
However, in managed forms 1C82 and in all versions of 1C83, this feature is already completely blocked (another loader appeared -
Connect External Component
() ).
Thus, in modern versions of 1C, you need to look for other simple alternatives to the “magic” lines of Fedorov-Orefkov.
And such an alternative is easy to offer. The point is simple. The 1C loader unloads the “wrong” component if it throws an exception when trying to access it using the specified protocol, for example, when requesting the version of the component. Naturally, we don’t have anything of this kind, which serves as the basis for unloading a non-standard dll. But the requirement of 1C for the operating system to unload this dynamic library can be ignored by the system if this VK is still used somewhere. Instead of the deletion itself, the system simply reduces the usage counter of the desired module. And physically delete no earlier than this counter is reset. Therefore, our task is to artificially increase this counter.
To do this, you can call our dll function WinAPI
LoadLibrary () again in the
DLL_THREAD_ATTACH section
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: { WCHAR szDllName[_MAX_PATH] = {0};
All! The problem is resolved. Recalling the same dynamic library will increase its usage counter by one, and unloading (with a preliminary
entry into the
DLL_THREAD_DETACH section) will decrease by one. Total we have
2 - 1 = 1> 0 , therefore, the operating system will not unload our dll. Moreover, what is important, reinitialization of the
DLL_PROCESS_ATTACH section will not occur.
From this, by the way, one can see how 1C can deal with a similar trick in its latest versions (and, apparently, it already does this in the configurations created in 1C-8.3.14 and higher). It can use the
LoadLibraryEx () function with a parameter that blocks the execution of the initialization section
DLL_PROCESS_ATTACH , after which it will immediately call the necessary exported functions. And, indeed, if you look at the code of the VK example for the Native API, you can see that there is no need to call the initialization code, since it must be empty by the VK format.
Regarding the examples of using COM technology, it is obvious that the execution of the initialization section
DLL_PROCESS_ATTACH is necessary there, therefore, in not too new versions of 1C, more precisely, in the configurations made in 1C-8.3.13 and below, the 1C loader is suitable for us:
(, , .COM);
Here the last parameter can be removed, since it is implied by default. At the same time, they can open normally in any higher version. In versions 1C83, the previous bootloader
LoadExternalComponent (Component Address) no longer suits us (respectively, the "magic lines" of Fedorov-Orefkov do not work there).
In the general case, as already mentioned, the problem can be solved by using an external bootloader. Or, which is quite natural, to observe, to one extent or another, the technology of the external components of 1C.
It should also be noted that the experiments we conducted in file versions of 1C with different bit depths. To download our component, you may need to set the “
Synchronous Call Usage Mode ” property to “
Use ” in the configuration.
It should also be understood that you carry out the use of such a technique at your own risk, experiment in advance on test configurations or copies of workers in order to avoid potential problems in the main programs.
Update from 09/11/2019
It turned out that I was worried in vain that: "in versions 1C-8.3.14 and above, the initialization section in the external component is no longer performed from the word" completely "."
It turns out that only the return message in the
ConnectExternalComponent () function does not need to be processed. Moreover, no matter what type of component we specify:
COM or
Native API .
Thus, you can create a configuration in all currently available versions of 1C, our component should work fine everywhere, and creating an external bootloader will be relevant, unless for the case when you do not want to change the configuration, which is fully supported.
In this regard, the code in the test configurations for 1C82 and 1C83 is slightly changed, although the differences between them are no longer fundamental.
At the same time, our remark that the 1C company can easily block the execution of the initialization code in any VK, at least for external components like the
Native API , obviously remains valid, because judging by their template, this is not necessary. For a VK type
COM, there is such a need so far, but what prevents it from getting rid of? At the same time, let’s see if they’ll take this information into account?