In C++11, using codeblocks 17.12, using GNU GCC Compiler, using UNICODE, on Windows XP Professional 32 bit with service pack 2. How do I make the three separate regions work independently of each other as described in the following? Not Visual Studio. Not ".net". Not C#.
If I have three simple images "a.bmp", "b.bmp", "c.bmp";
and I want them to each be regions with the white part not included;
and I want to be able to move each around on the screen independent of the others;
and I want the blue one to remain in front;
and I want the red one and the green one to be in front of each other when I right-mouse-click on them, but not in front of the blue one; I am trying to do this with Dialog boxes.
then how do I do this?
I have tried a lot of examples and book instructions, and now I want better help.
5 3696
Here is where I am: - #ifndef IDC_STATIC
-
#define IDC_STATIC (-1)
-
#endif
-
-
#ifndef _UNICODE
-
#define _UNICODE
-
#endif // _UNICODE
-
-
#ifndef UNICODE
-
#define UNICODE
-
#endif // UNICODE
-
-
// Not clear on if I need both _UNICODE and UNICODE .
-
-
#include "resource.h"
-
-
#include <windows.h>
-
//#include <commctrl.h> // Not clear on if I need this .
-
-
#define MAX_LOADSTRING 100
-
-
// Global Variables:
-
-
HINSTANCE InstanceHandleOfMainWindow; // Instance handle of the main window
-
-
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
-
// Why all the extra code for this? Why not just put the title directly into where the window is created?
-
// Why not make smaller code without this extra loadstring etc.?
-
-
HWND Handle_MainWindow = NULL; // Handle to main application window
-
-
HRGN hRgn = NULL; // Handle to region
-
-
HDC hdcDest; // Dest DC
-
-
HDC hdcMem; // Memory DC
-
-
BITMAP bmpInfo; // Buffer to hold bitmap data
-
-
BOOL mouseState = 0; // Global variable for moving region using mouse
-
-
POINT CursPt = {0}; // Global variable for moving region using mouse
-
-
wchar_t WindowClass_for_WinMain[MAX_LOADSTRING] = L"(myWindowClass)";
-
-
// Forward declarations of functions included later in this code module:
-
-
ATOM RegisterTheMainWindowClass(HINSTANCE hInstance2);
-
// Why rip this out of the WinMain and make a big deal of it? Why not just leave it in winMain?
-
-
BOOL DidTheMainWindowClassRegisterCorrectly(HINSTANCE, int);
-
-
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
-
-
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
-
-
// Empty function to be used later to create region based on the bitmap.
-
-
void createRegion(HWND);
-
-
// Empty Function to be used later to paint window regions.
-
-
void paintRegion();
-
-
// Empty Dialog callback procedure declaration to be used later.
-
-
INT_PTR CALLBACK DialogProc( HWND Handle_DialogBox1, UINT uMsg, WPARAM wParam, LPARAM lParam );
-
-
-
int APIENTRY WinMain(HINSTANCE hInstance1, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
-
-
{
-
MSG msg;
-
-
RegisterTheMainWindowClass(hInstance1);
-
-
if (!DidTheMainWindowClassRegisterCorrectly (hInstance1, nCmdShow))
-
{
-
return FALSE;
-
}
-
-
// Message loop
-
while (GetMessage(&msg, nullptr, 0, 0))
-
{
-
DispatchMessage(&msg);
-
}
-
-
return msg.wParam;
-
-
} //int APIENTRY WinMain(HINSTANCE hInstance1, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
-
-
-
ATOM RegisterTheMainWindowClass(HINSTANCE hInstance3)
-
-
// An ATOM is (always?) created when the class is registered.
-
// This might be a secure reference to window class in that it is special (?) to the kernel.
-
// Maybe (typedef unsigned short ATOM;)
-
// ATOM is a 16-bit Windows handle-like primitive.
-
// It's value is completely opaque to user-mode. (whatever that means)
-
// It is not a pointer or an index.
-
// They are indexes into a handle table in kernel mode.
-
// They are deliberately opaque because leaking kernel mode
-
// pointers to user-mode is a security violation (whatever that means).
-
{
-
WNDCLASSEX wcex;
-
-
wcex.cbSize = sizeof(WNDCLASSEX);
-
-
wcex.style = 0; // CS_HREDRAW | CS_VREDRAW;
-
// CS_HREDRAW is for HORIZONTAL;
-
// It redraws the entire window if a movement or size adjustment changes the width of the client area.
-
// CS_VREDRAW is for VERTICAL;
-
// It redraws the entire window if a movement or size adjustment changes the height of the client area.
-
wcex.lpfnWndProc = (WNDPROC)WndProc;
-
wcex.cbClsExtra = 0;
-
wcex.cbWndExtra = 0;
-
wcex.hInstance = hInstance3;
-
wcex.hIcon = nullptr;
-
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
-
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
-
wcex.lpszMenuName = nullptr;
-
wcex.lpszClassName = WindowClass_for_WinMain;
-
wcex.hIconSm = nullptr;
-
-
// Return type is ATOM.
-
return RegisterClassEx(&wcex);
-
-
} //ATOM RegisterTheMainWindowClass(HINSTANCE hInstance3)
-
-
BOOL DidTheMainWindowClassRegisterCorrectly(HINSTANCE hInstance4, int nCmdShow)
-
{
-
InstanceHandleOfMainWindow = hInstance4; // Store the instance handle in a previously created global variable
-
-
Handle_MainWindow = CreateWindow( // Should I use CreateWindowEx ?
-
WindowClass_for_WinMain,
-
szTitle,
-
WS_OVERLAPPEDWINDOW,
-
CW_USEDEFAULT,
-
0,
-
100,
-
150,
-
NULL,
-
NULL,
-
hInstance4,
-
NULL);
-
-
if (!Handle_MainWindow)
-
{
-
return FALSE;
-
}
-
-
// Create a dialog box
-
HWND Handle_DialogBox2 = CreateDialog(hInstance4, MAKEINTRESOURCE(IDD_DIALOG1), Handle_MainWindow, (DLGPROC)DialogProc);
-
-
// Create a region
-
createRegion(Handle_DialogBox2);
-
-
// Don't have to show or update the window ?
-
// ShowWindow(hWnd, nCmdShow);
-
// UpdateWindow(hWnd);
-
-
return TRUE;
-
-
} //BOOL DidTheMainWindowClassRegisterCorrectly(HINSTANCE hInstance4, int nCmdShow)
-
-
-
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-
{
-
switch (message)
-
{
-
-
case WM_DESTROY:
-
{
-
DeleteObject(hRgn);
-
-
DeleteDC(hdcMem); //Delete the memory DC
-
-
DeleteDC(hdcDest); //delete the dest DC
-
-
PostQuitMessage(0);
-
}
-
return TRUE;
-
break;
-
-
default:
-
{
-
}
-
return DefWindowProc(hWnd, message, wParam, lParam);
-
}
-
return 0;
-
-
} // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-
-
-
INT_PTR CALLBACK DialogProc(HWND Handle_DialogBox01, UINT uMsg, WPARAM wParam, LPARAM lParam )
-
// Dialog callback procedure
-
// // INT_PTR is a signed integer memsize-type
-
// // that can store a pointer regardless of the platform capacity.
-
// HWND Handle_DialogBox01, // Temporary (internal to this procedure) Handle to a dialog box
-
// UINT uMsg, // Message
-
// WPARAM wParam, // First message parameter
-
// LPARAM lParam // Second message parameter
-
{
-
-
switch (uMsg)
-
{
-
-
case WM_PAINT:
-
{
-
paintRegion();
-
-
ValidateRect(Handle_DialogBox01,nullptr); // ValidateRect(hwnd,FALSE);
-
}
-
return TRUE;
-
break;
-
-
case WM_MOVE:
-
{
-
paintRegion();
-
}
-
return TRUE;
-
break;
-
-
-
case WM_LBUTTONDOWN:
-
{
-
mouseState = 1;
-
}
-
return TRUE;
-
break;
-
-
case WM_MOUSEMOVE:
-
{
-
if(mouseState)
-
{
-
GetCursorPos(&CursPt);
-
PostMessage(Handle_DialogBox01, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( CursPt.x, CursPt.y));
-
mouseState = 0;
-
}
-
-
}
-
return TRUE;
-
break;
-
-
case WM_RBUTTONDOWN:
-
{
-
// Destroy the dialog box
-
EndDialog(Handle_DialogBox01,0);
-
-
// Send message to destroy the main application window and exit
-
SendMessage(Handle_MainWindow,WM_DESTROY,0,0);
-
}
-
return TRUE;
-
break;
-
-
default :
-
{
-
break;
-
}
-
return TRUE;
-
break;
-
}
-
return FALSE;
-
-
} // INT_PTR CALLBACK DialogProc( HWND Handle_DialogBox01, UINT uMsg, WPARAM wParam, LPARAM lParam )
-
-
void createRegion(HWND FunctionReferenceTo_DialogBox01)
-
{
-
-
COLORREF crTransparent;
-
-
int iX = 0;
-
int iY = 0;
-
-
int iRet01 = 0; // Integer For region 1
-
int iRet02 = 0; // Integer For region 2
-
-
-
// Get the destination device context
-
hdcDest = GetDC(FunctionReferenceTo_DialogBox01);
-
-
// Create a memory DC
-
hdcMem = CreateCompatibleDC(nullptr);
-
-
-
//----------------------------------------------------------------------
-
// START Load the image files
-
//----------------------------------------------------------------------
-
-
// a.bmp
-
-
wchar_t imageFile_A[] = L"a.bmp";
-
-
// Load the image
-
HANDLE Handle_Bitmap_A = (HBITMAP)LoadImage(GetModuleHandle(nullptr), imageFile_A, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
-
-
if(!Handle_Bitmap_A)
-
{
-
// Handle error here
-
return;
-
}
-
-
-
// b.bmp
-
-
wchar_t imageFile_B[] = L"b.bmp";
-
-
// Load the image
-
HANDLE Handle_Bitmap_B = (HBITMAP)LoadImage(GetModuleHandle(nullptr), imageFile_B, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
-
-
if(!Handle_Bitmap_B)
-
{
-
// Handle error here
-
return;
-
}
-
-
//----------------------------------------------------------------------
-
// END Load the image files
-
//----------------------------------------------------------------------
-
-
-
-
//----------------------------------------------------------------------
-
// START Create Region from imageFile_A
-
//----------------------------------------------------------------------
-
-
HRGN TemporaryRegion_for_Bitmap_A;
-
HRGN FinalTransparentRegionFromBitmap_A;
-
-
-
// Get information about the bitmap..
-
GetObject(Handle_Bitmap_A, sizeof(bmpInfo), &bmpInfo); // Get info about the bitmap
-
-
// Select the bitmap into the dc
-
//hGdiObj = SelectObject(hdcMem, Handle_Bitmap_A);
-
SelectObject(hdcMem, Handle_Bitmap_A);
-
// Create a region from a bitmap with transparency colour of white
-
// change the pixel values for a different transparency color
-
// example - RGB(0,0,0) will mean a transparency color of black.. so the areas
-
// of the bitmap not used to create the window will be black
-
// COLORREF crTransparent = RGB(255, 255, 255);
-
crTransparent = RGB(255, 255, 255);
-
-
-
iX = 0;
-
iY = 0;
-
iRet01 = 0; // For region 2
-
-
FinalTransparentRegionFromBitmap_A = CreateRectRgn(0,0,0,0);
-
-
for (iY = 0; iY < bmpInfo.bmHeight; iY++)
-
{
-
do
-
{
-
// Skip over transparent pixels at start of lines.
-
while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY) == crTransparent)
-
{
-
iX++;
-
}
-
-
// Remember this pixel
-
int iLeftX = iX;
-
-
// Now find first non transparent pixel
-
while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY) != crTransparent)
-
{
-
++iX;
-
}
-
-
// Create a temp region on this info
-
TemporaryRegion_for_Bitmap_A = CreateRectRgn(iLeftX, iY, iX, iY+1);
-
-
// Combine into main region.
-
// From wingdi.h
-
// WINGDIAPI int WINAPI CombineRgn(HRGN,HRGN,HRGN,int);
-
// Combine Region1 & Region2 & store result in ResultRegion.
-
// CombineRgn(ResultRegion,Region1,Region2,RGN_AND);
-
iRet01 = CombineRgn(FinalTransparentRegionFromBitmap_A, FinalTransparentRegionFromBitmap_A, TemporaryRegion_for_Bitmap_A, RGN_OR);
-
-
-
-
}
-
-
while(iX < bmpInfo.bmWidth);
-
{
-
iX = 0;
-
}
-
}
-
-
// Center it on current desktop
-
iRet01 = SetWindowRgn(FunctionReferenceTo_DialogBox01, FinalTransparentRegionFromBitmap_A, TRUE);
-
-
if(!iRet01)
-
{
-
return;
-
}
-
-
iX = (GetSystemMetrics(SM_CXSCREEN)) / 3 - (bmpInfo.bmWidth / 3);
-
-
iY = (GetSystemMetrics(SM_CYSCREEN)) / 3 - (bmpInfo.bmHeight / 3);
-
-
iRet01 = SetWindowPos(FunctionReferenceTo_DialogBox01, HWND_TOPMOST, iX, iY, bmpInfo.bmWidth, bmpInfo.bmHeight, 0);
-
-
//----------------------------------------------------------------------
-
// END Create Region from imageFile_A
-
//----------------------------------------------------------------------
-
-
-
//----------------------------------------------------------------------------------------------------
-
//----------------------------------------------------------------------------------------------------
-
//----------------------------------------------------------------------------------------------------
-
-
-
//----------------------------------------------------------------------
-
// START Create Region from imageFile_B
-
//----------------------------------------------------------------------
-
-
HRGN TemporaryRegion_for_Bitmap_B;
-
HRGN FinalTransparentRegionFromBitmap_B;
-
-
-
// Get information about the bitmap..
-
GetObject(Handle_Bitmap_B, sizeof(bmpInfo), &bmpInfo); // Get info about the bitmap
-
-
// Select the bitmap into the dc
-
SelectObject(hdcMem, Handle_Bitmap_B);
-
-
// Create a region from a bitmap with transparency colour of white
-
// change the pixel values for a different transparency color
-
// example - RGB(0,0,0) will mean a transparency color of black.. so the areas
-
// of the bitmap not used to create the window will be black
-
// COLORREF crTransparent = RGB(255, 255, 255);
-
crTransparent = RGB(255, 255, 255);
-
-
-
iX = 0;
-
iY = 0;
-
iRet02 = 0; // For region 2
-
-
FinalTransparentRegionFromBitmap_B = CreateRectRgn(0,0,0,0);
-
-
for (iY = 0; iY < bmpInfo.bmHeight; iY++)
-
{
-
do
-
{
-
// Skip over transparent pixels at start of lines.
-
while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY) == crTransparent)
-
{
-
iX++;
-
}
-
-
// Remember this pixel
-
int iLeftX = iX;
-
-
// Now find first non transparent pixel
-
while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY) != crTransparent)
-
{
-
++iX;
-
}
-
-
// Create a temp region on this info
-
TemporaryRegion_for_Bitmap_B = CreateRectRgn(iLeftX, iY, iX, iY+1);
-
-
// Combine into main region.
-
// From wingdi.h
-
// WINGDIAPI int WINAPI CombineRgn(HRGN,HRGN,HRGN,int);
-
// Combine Region1 & Region2 & store result in ResultRegion.
-
// CombineRgn(ResultRegion,Region1,Region2,RGN_AND);
-
iRet02 = CombineRgn(FinalTransparentRegionFromBitmap_B, FinalTransparentRegionFromBitmap_B, TemporaryRegion_for_Bitmap_B, RGN_OR);
-
-
}
-
-
while(iX < bmpInfo.bmWidth);
-
{
-
iX = 0;
-
}
-
}
-
-
// Center it on current desktop
-
iRet02 = SetWindowRgn(FunctionReferenceTo_DialogBox01, FinalTransparentRegionFromBitmap_B, TRUE);
-
-
if(!iRet02)
-
{
-
return;
-
}
-
-
iX = (GetSystemMetrics(SM_CXSCREEN)) / 3 - (bmpInfo.bmWidth / 3);
-
-
iY = (GetSystemMetrics(SM_CYSCREEN)) / 3 - (bmpInfo.bmHeight / 3);
-
-
iRet02 = SetWindowPos(FunctionReferenceTo_DialogBox01, HWND_TOPMOST, iX, iY, bmpInfo.bmWidth, bmpInfo.bmHeight, 0);
-
-
//----------------------------------------------------------------------
-
// END Create Region from imageFile_B
-
//----------------------------------------------------------------------
-
-
-
// Copy the memory dc into the screen dc
-
paintRegion();
-
-
// Delete the bitmap
-
DeleteObject(Handle_Bitmap_A);
-
DeleteObject(Handle_Bitmap_B);
-
-
} // void createRegion(HWND FunctionReferenceTo_DialogBox01)
-
-
void paintRegion()
-
{
-
// Transfer color data from the source device context to the destination device context
-
BitBlt(hdcDest, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, hdcMem, 0, 0, SRCCOPY);
-
}
Here are some pictures showing what I am doing:
Thank you gits for fixing the code to show indentations, etc. That was nice of you. I shall try to post code correctly formatted for viewing in the future. I copy and pasted this code, but that was not sufficient. You fixed it. Thank you. I shall try to do better next time.
Also. I have been experimenting and got the code to work better in that it shows both of the images, but it greys out one of them. Should I replace the original code with the updated code in my original posting, or post it separately?
So far, to date 1/8/2020, this post has been viewed 224 times. Still no one told me how to do this. I need some help. C++ is new to me. Please someone tell me how to do this. I can create a region. I can create two regions, one at a time. I do not have to do this with dialog boxes if there is another or better/faster way. Help! Please.
In Microsoft Windows:
Do not use dialog boxes.
"I am trying to do this with Dialog boxes."
If you use standard dialog boxes then you are adding another window handle to your program. That allows Microsoft to add bloat to your program. Try to avoid adding any and all "additional" window handles to your program if you can. Sometimes it is necessary, but work at not having them.
You are working with images, therefore stay with images and use mouse tracking to detect when your mouse is over each of the images.
Since you are using regions then you might already have somewhere in your code the x and y positions of the entire pixel layout of each of your images. Your current front image's pixels would be subtracted from any and all images behind it. Your most rearward image would have all forward image pixels subtracted from it. Track you mouse position. Detect when the mouse is over a specific image. If a click occurs then respond as though it were a click on that image.
Start with creating two buffers. - Initialize the back most buffer.
- Place all of your images on that buffer from back most image to front most image.
- Initialize the front most buffer.
- Do your image manipulation in the back most buffer.
- Copy that buffer to the front buffer.
- Copy that buffer to the screen.
You now have your image manipulation in buffers and not directly to the screen. Thus, less chance for screen flickering.
You now have two buffers that you can work with. The back most buffer you are currently using. The front most buffer is already set up, but not being actively used, and ready for testing later use. With the extra buffer you have an expansion option already built in. Example: you might want to do some testing of image effects and you do not want to damage your existing code, so do the testing in the front buffer where you can delete the entire test however complicated and intricate it is without it being tightly integrated into your current (back-most buffered) code.
Maybe, if someone has the time they might give you the code to do this, or maybe if later I have the time I might strip some out of one of my programs. But, this is how it can be done.
I see that you are using XP sp2. Since you are knowledgeable about the security of why to not use beyond that, then I expect that you might know at least some of the security of why to avoid using a lot of un-necessary Windows handles.
Going through the process again so that you understand what I am saying:
Buffers;
Images to buffers;
Mouse to pixel location detection;
Respond with rebuilding the back most buffer with images in the order that you want back most to front most.
Then copy back buffer to front buffer.
The next two things should be in one thread with no delays in between them. Not in two separate threads! - Re-analyze your mouse positioning. You are doing this part again BEFORE PLACING THE FRONT BUFFER TO THE SCREEN: Configure your tracking for the mouse position for the new image setup positions. No responses yet. Just set up the tracking for the new image placement.
- Then copy the front buffer to the screen.
The user sees the screen.
Sign in to post your reply or Sign up for a free account.
Similar topics
by: Michael N. Christoff |
last post by:
Java, the software developed by Sun Microsystems in the mid-1990s as a
universal operating system for Internet applications, gave NASA a low-cost
and easy-to-use option for running Spirit, the...
|
by: Iain |
last post by:
I'm part way through a project which will create Data Access classes for SQL
Server database more or less automatically from the table definitions in the
DB itself.
I sort of get the CodeDom...
|
by: C# Learner |
last post by:
1) How often do you put regions into your code?
a) very often
b) occasionally
c) infrequently
d) never
2) If you didn't answer (d), what do you use regions for?
a) hiding ugly code
|
by: Simon |
last post by:
Just starting on C# and would like to know what suggestions
there are for the order in which declarations, event
handlers, properties, private code, nested classes, etc,
etc appear in your files....
|
by: G B |
last post by:
Hi guys
I was wondering whether generating Regions is possible using the
CodeDom.
I am writing a tool that generates some code and I could not find a way
to group code into regions.
Has...
|
by: gaidar |
last post by:
Hi, everybody,
I'm just wondering if someone really need stuff like this:
http://msdn2.microsoft.com/library/ms123401.aspx. If you answer yes than
explain, please.
Thanks!
Gaidar
|
by: steve |
last post by:
Hello,
I am having a problem with an index controlled partitioned table. I
was altering a table using SQL. I was trying to add a partition to a
table to change it from index controlled to...
|
by: Ikke |
last post by:
Hi everybody,
Can somebody tell me how to disable regions in Visual Studio 2005?
I've already told VS not to collapse code to regions in the settings, but
each time I open a new (existing)...
|
by: Spleenwort |
last post by:
With regard to XML comments in c#.
I think that #regions should be self-documenting relative to XML
comments or that a <region> tag should be defined and auto-inserted
when you type #region...
|
by: Mike |
last post by:
I've a datagrid containing user's information which onselect displays
a detailsview control
in edit mode I've set-up two template fields to map to (country) and
(region) these are dropdownlists...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
| |